简单来说,就是完成下图这个需求。
地图上这条线实在QGIS中做的数据。
点击这条线的时候,要求获取这条线的数据以及让这条线高亮。虽说简单,做起来还是有些复杂。
我大概分两步解决。
第一步,解决点击事件
// 引入openlayer相关的包
import { Image as ImageLayer } from 'ol/layer';
import { ImageWMS } from 'ol/source';
// 首先通过加载ImageWMS服务,构建一个图片图层 ImageLayer
const LINE_LAYER = new ImageLayer({
id: 'line', // 唯一标识 随便写 不要重复
zINdex: 2, // 显示层级
source: new ImageWMS({
url: 'xxxx',// 这里需要写上GEOserver发布的服务地址
params: { // 服务参数 很重要 参数写不对 图层加载不出来
LAYERS: 'xxxx', // 根据发布服务写
},
ratio: 1,// 这个是比例 具体看文档
serverType: 'geoserver', // geoserver 发布的服务
})
})
// 图层建立完毕之后 需要调用 map的addLayer添加图层
// 要注意 这里写的map是已经在上边实例化过的
// 用上边实例化之后的map,添加刚刚创建的线路图层
map.addLayer(LINE_LAYER);
// ****** 下边开始处理点击事件 ******
map.on('singleclick', (e) => {
// 这个点击事件是针对地图上所有的图层的
// 所以你要先获取希望点击事件起作用的图层
// 我们这里是想让点击事件在 上边建立的 LINE_LAYER 上起作用
let source = LINE_LAYER.get(visible) ? LINE_LAYER.getSource() : void(0);
if (!source) return; // 要是不存在我们想要的图层 就算了
// 获取视图 一会要用
let view = map.getView();
// 获取分辨率
let viewResolution = view.getResolution();
// 最后需要通过 ImageWMS 的api --- getFeatureInfoUrl 去获取地图上所点击的要素 也就是线
// 首先获取服务的URL
let url = source.getFeatureInfoUrl(
e.coordinate,
viewResolution,
view.getProjection(), // 获取投影 比如是 ’EPSG:4366‘
{
INFO_FORMAT: 'application/json', // 这里有很多种格式,既然是请求 我希望他返json
}
);
if (url) {
fetch(url).then(data => return data.json()).then(res => {
// 这里的res就是我们点击事件 获取的要素 也就是点击的线路
/**
res的格式大致是这样的:
{
crs: {},
features: [],
.....
}
*/
})
// 很明显 我们需要 feature 这个字段,它就是我们点击选中的要素
// 获取这个要素
let feature = res?.feature?.[0];
// 暂时到这里我们解决了点击事件 可以获取到所点击选中的要素了
}
})
第二步,解决点击高亮
解决高亮一直困扰我大半天。虽然查了很多资料,但没有一个是奏效。最终综合网上版本,得到了如下代码:
// 这里还是需要引入矢量图层和矢量源 几何形状
import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';
import Feature from 'ol/Feature';
import MultiLineString from 'ol/geom/MultiLineString';
// 以下代码还是在上边写过的 map.on('singleclick', () => {}) 回调函数中
map.on('singleclick', () => {
// 先判断高亮图层是否已经再地图上存在了,如果存在,就移除这个高亮图层
// 这样做保证每次只选中一条线,同时也避免了添加次数过多,占用内存的风险
if (this.channnelLayer) {
map.removeLayer(this.channnelLayer);
}
// vue数据中定义一个高亮图层数据 用于存储高亮图层
// 创建一个 矢量图层
this.channnelLayer = new VectorLayer({
source: new VectorSource(), // source 是必须的
zIndex: 9
});
// 创建一个几何形状 这一步很重要 这个新创建的几何图形就是我们需要的高亮图层
// 这个几何形状 就是我们选中的线集合
// 所以 需要传入我们选中这个线集合的所有点集合
// 首先 获取选中线条的所有点的坐标集合
let feature_coord = feature?.feature?.[0]?.geometry?.coordinates;
let highlightFeature = new Feature({
geometry: new MultiLineString(feature_coord )
})
// 设置这个图层的一些基本属性
highlightFeature.setProperties({
id: feature?.id,
name: feature?.geometry_name,
type: 'channel'
})
// 开始设置高亮颜色
highlightFeature.setStyle({
new Style({
fill: new Fill({
color: '#f40'
}),
stroke: {
color: '#121211',
width: 6
},
})
})
// 图层建立完毕之后 还是分两步
// 第一步,图层添加几何形状
// 第二步,地图添加图层
this.channnelLayer.getSource().addFeature(highlightFeature);
map.addLayer(this.channnelLayer);
/***** 至此点击高亮结束 *****/
})