1. 程式人生 > 實用技巧 >openlayers 聚合圖層點選事件--點選feature展示相關資訊操作

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         },