聚合情況下,點擊聚合要素,則顯示聚合的設備信息;若只有一個要素,則顯示設備信息;聚合情況下:點擊設備信息,則繼續彈出點擊的這個設備詳情
業務功能分析:
獲取地圖上的點擊要素方法有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 },