vue openlayer GisMap QGis 点击交互 MultiLineString 样式高亮

简单来说,就是完成下图这个需求。

vue openlayer GisMap QGis 点击交互 MultiLineString 样式高亮_第1张图片

 地图上这条线实在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);



    /*****  至此点击高亮结束 *****/
})

你可能感兴趣的:(vue,css,html,javascript,前端)