关于VUE项目地图开发中大量点标记绘制一些总结
問題說明
在地圖開發中,當地圖中繪制大量的標記點后,無論是拖動或者縮放,都會感覺到明顯的卡頓現象。(一般超過800個點后就比較明顯了).在平時的工作業務中,由于公司的實時監控頁面需要展現5000-20000車輛的實時定位跟蹤,特別是切換到車輛密集的港口碼頭卡頓現象非常嚴重(如下圖),看起來非常難看,用戶體驗也非常差。在此寫下一些開發優化中的心得體會(本文中使用的是高德地圖為參考)。
解決思路
首先我們應該將地圖上的所有覆蓋物(包括Marker,Icon,Text,Polygon)分組添加到多個OverlayGroup中對每一類統一管理。部分覆蓋物默認隱藏,需要時才展現。
不要將大量的覆蓋物信息都直接掛載在地圖對象上,可以按需加載,減少地圖在移動后重新渲染的工作量
合理的使用覆蓋物聚合(聚合雖然會減少卡頓,但是覆蓋物數量太多依舊會比較卡)
解決方法
首先,添加一個地圖設置勾選面板,將除車輛點標記以外的所有覆蓋物按類型分類,添加到一個個單獨的OverlayGroup中默認不掛載在地圖上,在勾選時才調用OverlayGroup.setMap(map)方法添加到地圖上。去掉了這些不必要覆蓋物,首次進入時立馬清爽了許多。
盡管去掉了各類網點,文字,等覆蓋物,但是我們需要渲染的車輛標記點依舊是非常多的。在此基礎上,我們采用按屏幕加載,篩選出屏幕內的點,屏幕外的標記點不渲染,監控每次地圖的moveend,zoomend,resize,每次的改變后重新計算屏幕內的標記點,當屏幕內標記點較少,比如200以下(這個隨個人需要定),直接繪制在地圖上。當屏幕內標記點比較多,大于200,調用聚合方法,將標記點聚合后繪制在地圖上。
參考代碼
/**監聽地圖拖拽,放大事件,根據屏幕范圍動態渲染點位 */reloadMarks(){AMap.event.addListener(this.map,'moveend',()=> {this.computeMarkers();})AMap.event.addListener(this.map,'zoomend',()=> {this.computeMarkers();})AMap.event.addListener(this.map,'resize',()=> {this.computeMarkers();})},/** 根據當前屏幕范圍帥選marker */computeMarkers(){this.newViewData={};//獲取當前視圖范圍let now_bounds = this.map.getBounds();//遍歷車輛數據,為了減少后臺傳入的重復數據,我的車輛信息列表一直使用對象保存for(let sel_deviceNo in this.carDataObj0){let item=this.carDataObj0[sel_deviceNo];//判斷當前點的坐標是否存在于視圖內if(now_bounds.contains(item.gcj02_coords.split(','))){//將當前屏幕內的視圖點保存this.newViewData[sel_deviceNo] = item;}}this.renderMarker();now_bounds=null;},/** 創建聚合**/createCluser(markerArr) {AMap.plugin(['AMap.MarkerClusterer'], () => {this.cluster = new AMap.MarkerClusterer(this.map, markerArr, {gridSize: 80,renderCluserMarker,minClusterSize: 1,maxZoom: 18});})},/** 將markers渲染到map上 */renderMarker(){//判斷目前是否有當前覆蓋物組!this.overLayGroup && this.overLayGroup = new AMap.OverlayGroup([]);let MarkerAddArr = [];for(let sel_deviceNo in this.newViewData){/**我的所有創建的Marker點對象都是長期存在于this.markerObj中,并不銷毀,每次數據更新后調用marker對象的setPosition(),setAngle(),setIcon()等方法改變狀態,再篩選出需要掛載上的一起加到地圖上 **/if(this.markerObj[sel_deviceNo]){MarkerAddArr.push(this.markerObj[sel_deviceNo]);}}this.overLayGroup.clearOverlays();//超過200個點則開啟聚合模式 且在聚合模式下不渲染面板展示點if(MarkerAddArr.length>=200){if(this.cluster){this.cluster.clearMarkers();this.cluster.setMarkers(MarkerAddArr);}else{this.createCluser(MarkerAddArr);}}else{if(this.cluster){this.cluster.clearMarkers();}this.overLayGroup.addOverlays(MarkerAddArr);this.overLayGroup.setMap(this.map);}MarkerAddArr=null;},代碼直接從業務中復制的,耦合度比較高,還請見諒。 做完了標記點按屏幕分組加載之后,我們在添加一個簡單的防抖方法,防止連續的拖動或者縮放導致computeMarkers方法被觸發,減少方法調用次數
const debounce = (fn, wait=500) =>{return function() {clearTimeout(fn.timer)fn.timer = setTimeout(fn.bind(this, ...arguments), wait)} }完成后效果如下:減少了地圖的計算與渲染,每次只計算視野內的點數,因此總數的大小不會影響地圖性能,當視野內超過200個點都會聚合,200以下時顯示。
平時寫文章比較少,文筆很差,還請多多見諒,謝謝。總結
以上是生活随笔為你收集整理的关于VUE项目地图开发中大量点标记绘制一些总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 开源|蚂蚁金服开源AntV F2:一个专
- 下一篇: Web 开发中 Blob 与 FileA