openlayers 聚合图层点击事件--点击feature展示相关信息操作
聚合情况下,点击聚合要素,则显示聚合的设备信息;若只有一个要素,则显示设备信息;聚合情况下:点击设备信息,则继续弹出点击的这个设备详情
业务功能分析:
获取地图上的点击要素方法有2种途径,
1、interaction中select方法
2、map中forEachFeatureAtPixel方法
其中,当数据量多大的时候,是不建议采用第二种方法,因为forEachFeatureAtPixel的原理,是遍历操作,当数据量大的时候,页面容易卡顿;因此建议采用第一种方法;
在以下的地图初始化方法init中,
this.clickMap(evt)方法,就是采用了第二种map中forEachFeatureAtPixel的做法,因此被注释;
this.featureClick()方法,是后来后来优化的方法,采用第一种interaction中select方法 。
仅截取部分核心代码,仅供借鉴
1、地图部分代码
其中
id="map"是地图渲染的部分
ref="overlayPopup"是设备信息弹窗
ref="deviceListPopup" 设备聚合列表弹窗
1 <el-container style="position: relative;"> 2 <div id="map" class="map"></div> 3 <!-- 自定义开发控件 --> 4 <div class="tool-box" v-show="hasLoadMap"> 5 <map-operation :map="map"></map-operation> 6 </div> 7 <!-- 设备信息弹窗 --> 8 <div class="ol-popup" ref="overlayPopup"> 9 <div class="close-icon" @click="closeVideoPopup">x</div> 10 <div> 11 <div class="vedio-selection" @click="showPlayBox(1)">监测</div> 12 <div class="vedio-selection" @click="showPlayBox(2)">回放</div> 13 <div class="vedio-selection" @click="showDeviceInfoBox" v-if="dockingOneForOne">设备信息</div> 14 </div> 15 <div class="eachItem">名称:{{popupDeviceInfo.dev_chann_name}}</div> 16 <div class="eachItem">类型:{{popupDeviceInfo.channel_type}}</div> 17 </div> 18 <!-- 设备聚合列表弹窗 --> 19 <div class="ol-popup-devicelist" ref="deviceListPopup"> 20 <div class="close-icon" @click="closeDevicePopup">x</div> 21 <div class="popupTitle">设备信息 22 <span class="popupsubTitle">(合计{{popupDeviceList.length}}个)</span> 23 </div> 24 <div class="popupDeviceOutter"> 25 <div v-for="(item,index) in popupDeviceList" :key="index" class="eachItem" :title="item.dev_chann_name" @click="showDeviceInfoFun(item)"> 26 <span class="indexCls">{{index+1}}、</span> 27 <img :src="rspImg(item.facade, item.status)" class="popupImg"> 28 {{item.dev_chann_name}} 29 </div> 30 </div> 31 </div> 32 </el-container>
2、地图初始化代码
#method里面
1 //初始化 2 init() { 3 let appCode = 'appCode'; 4 let layersUrl = sessionStorage.getItem('mapUrl'); 5 let viewCenter = JSON.parse(sessionStorage.getItem('viewCenter')); 6 let mapLayer = initMapLayer(_data.mapType, layersUrl); 7 8 ///鸟瞰图控件 9 this.OverviewMapObj = new ol.control.OverviewMap({ 10 collapsed: false, 11 view: new ol.View({ 12 center: viewCenter, 13 maxZoom: 18, 14 minZoom: 12, 15 zoom: 13, 16 projection: 'EPSG:4326', //需要跟map中的view一致 17 }), 18 }); 19 this.map = new ol.Map({ 20 layers: mapLayer, 21 view: new ol.View({ 22 center: viewCenter, 23 maxZoom: 18, 24 minZoom: 8, 25 zoom: 13, 26 projection: 'EPSG:4326', 27 }), 28 controls: ol.control.defaults({ 29 zoomOptions: { 30 zoomInTipLabel: '放大', //Default is Zoom in 31 zoomOutTipLabel: '缩小', //Default is Zoom out 32 }, 33 }).extend([ 34 new ol.control.MousePosition({ 35 coordinateFormat: ol.coordinate.createStringXY(5), //保留5位小数 36 }), 37 new ol.control.ScaleLine(), 38 // new ol.control.ZoomSlider(), 39 this.OverviewMapObj 40 ]), 41 interactions: ol.interaction.defaults({ 42 doubleClickZoom: false, // 取消双击放大功能交互 43 }), 44 target: 'map', 45 }); 46 47 // 双击事件 48 this.map.on('dblclick', evt => { 49 this.dbclickMap(evt); 50 }); 51 // 单击事件 52 // this.map.on('click', evt => { 53 // this.clickMap(evt); 54 // }); 55 this.featureClick(); // 要素点击事件 56 // this.addListener(); 57 },
3、地图点击事件
对应init里面的click事件
1 //点击事件 2 clickMap(evt) { 3 let featureMouseOver = this.map.forEachFeatureAtPixel(evt.pixel, function (feature, layer) { 4 return feature; 5 }); 6 if (!featureMouseOver) return 7 let overFeature = featureMouseOver.getProperties().features 8 if(!overFeature || overFeature.length == 0) return false 9 if (overFeature.length === 1) {// 只有一个元素的情况下 10 let feature = overFeature[0]; //获取该要素 11 let featureData = feature.get('data') || {} 12 this.showFeature(featureData, evt.coordinate) 13 } else if(overFeature.length > 1){// 多个元素的情况下 14 this.showFeatureList(overFeature, evt.coordinate) // 展示设备列表 15 } 16 },
4、地图要素select事件
1 // 给页面的要素添加点击事件 2 featureClick(evt) { 3 var selectSingleClick = new ol.interaction.Select({ 4 style: new ol.style.Style({ 5 image: new ol.style.Circle({ 6 radius: 18, 7 fill: new ol.style.Fill({ 8 color: 'rgba(70,220,198,0.5)' 9 }) 10 }) 11 }) 12 }); 13 this.map.addInteraction(selectSingleClick); 14 selectSingleClick.on('select', e =>{ 15 var featuresAry=e.target.getFeatures().getArray(); 16 if (featuresAry.length>0){ 17 let featureList=featuresAry[0]; 18 let coordinate = ol.extent.getCenter(featureList.getGeometry().getExtent()); // 点击的点经纬度 19 // 至此得出聚合图层的要素列表 20 let features=featureList.getProperties().features; 21 this.closeDevicePopup() // 关闭已打开的列表popup 22 this.closeVideoPopup() // 关闭已打开的详情popup 23 if(features.length == 1 ) { 24 let featureData = features[0].get('data') || {} 25 this.showFeature(featureData, coordinate) 26 } else if(features.length > 1) { 27 this.showFeatureList(features, coordinate) // 展示设备列表 28 } 29 } 30 }) 31 },
5、地图双击事件。
聚合点击时,和双击事件关系不大,此处仅为记录双击的事件而言
1 //双击地图事件 2 dbclickMap(evt) { 3 let featureMouseOver = this.map.forEachFeatureAtPixel(evt.pixel, function (feature, layer) { 4 return feature; 5 }); 6 if (featureMouseOver) { 7 let featureProperties = featureMouseOver.getProperties(); 8 if (!featureProperties.features) return; 9 //聚合情况下 10 if (featureProperties.features.length > 1) { 11 //双击聚合图层放大 12 let view = this.map.getView(); 13 view.setZoom(view.getZoom() + 2); 14 view.setCenter(featureMouseOver.getGeometry().getCoordinates()); //设置地图显示中心 15 } 16 } 17 },
6、查看详情和查看列表方法
附加代码:
1 // popup展示,聚合列表数据 2 showFeatureList(overFeature, coordinate) { 3 this.popupDeviceList = [] 4 overFeature.forEach(itemFeature =>{ 5 const itemFeatureData = itemFeature.get('data') || {} 6 this.popupDeviceList.push(itemFeatureData) 7 }) 8 let deviceListPopup = this.$refs.deviceListPopup; 9 if (!_data.deviceListPopup) { 10 _data.deviceListPopup = new ol.Overlay({ 11 element: deviceListPopup, 12 offset: [10, 0], 13 }); 14 deviceListPopup.style.display = 'block'; 15 this.map.addOverlay(_data.deviceListPopup); 16 } else { 17 deviceListPopup.style.display = 'block'; 18 _data.deviceListPopup.setOffset([10, 0]); // 设置偏移量 19 _data.deviceListPopup.setElement(deviceListPopup); 20 } 21 _data.deviceListPopup.setPosition(coordinate); 22 }, 23 //popup展示设备的具体信息 24 showFeature(featureData, coordinate) { 25 let overlayPopup = this.$refs.overlayPopup; 26 this.popupDeviceInfo = featureData 27 if (!_data.overlayPopup) { 28 _data.overlayPopup = new ol.Overlay({ 29 element: overlayPopup, 30 offset: [10, 0], 31 }); 32 overlayPopup.style.display = 'block'; 33 this.map.addOverlay(_data.overlayPopup); 34 } else { 35 overlayPopup.style.display = 'block'; 36 _data.overlayPopup.setOffset([10, 0]); // 设置偏移量 37 _data.overlayPopup.setElement(overlayPopup); 38 } 39 _data.overlayPopup.setPosition(coordinate); 40 this.setCurrentDevice(featureData) 41 }, 42 //关闭overlayPopup 43 closeVideoPopup() { 44 let overlayPopup = this.$refs.overlayPopup; 45 overlayPopup.style.display = 'none'; 46 }, 47 //关闭overlayPopup 48 closeDevicePopup() { 49 let deviceListPopup = this.$refs.deviceListPopup; 50 deviceListPopup.style.display = 'none'; 51 },