前言
leaflet 入門開發系列環境知識點了解:
- leaflet api檔案介紹,詳細介紹 leaflet 每個類的函式以及屬性等等
- leaflet 在線例子
- leaflet 插件,leaflet 的插件庫,非常有用
內容概覽
leaflet快速渲染聚合矢量瓦片
源代碼demo下載
錄制演示視頻
效果圖如下:

具體實作思路:leaflet結合Web Worker技術,借助supercluster插件,實作leaflet快速展示聚合效果,矢量瓦片請求資料源部分也放在Worker執行緒來處理,避免阻塞主執行緒UI互動部分回應,
測驗資料:聚合點23.8w,矢量瓦片資料源15w左右,
參考關鍵技術點:
1.Web Worker:Web Worker的作用,就是為JavaScript創造多執行緒環境,允許主執行緒創建Worker執行緒,將一些任務分配給后者運行,在主執行緒運行的同時,Worker執行緒在后臺運行,兩者互不干擾,等到 Worker 執行緒完成計算任務,再把結果回傳給主執行緒,這樣的好處是,一些計算密集型或高延遲的任務,被Worker執行緒負擔了,主執行緒(通常負責 UI 互動)就會很流暢,不會被阻塞或拖慢,
2.supercluster插件:supercluster插件
- 完整的見原始碼demo下載,聚合效果實作部分思路:
1.supercluster插件把聚合點資料源預處理,按照矢量瓦片思路提前把聚合點資料源切片處理好,每個級別對應的聚合點數以及對應資料源(zoom,count,data);
2.leaflet通過監聽地圖范圍變化事件,主執行緒跟worker子執行緒之間互相通信互動,然后leaflet根據worker子執行緒回傳來的資料源,動態重繪聚合資料,
主執行緒部分: const markers = L.geoJson(null, { pointToLayer: createClusterIcon }).addTo(map); var worker = new Worker('worker.js'); let ready = false; worker.onmessage = function (e) { if (e.data.ready) { ready = true; update(); } else if (e.data.expansionZoom) { map.flyTo(e.data.center, e.data.expansionZoom); } else { markers.clearLayers(); markers.addData(e.data); } }; function update() { if (!ready) return; const bounds = map.getBounds(); worker.postMessage({ bbox: [bounds.getWest(), bounds.getSouth(), bounds.getEast(), bounds.getNorth()], zoom: map.getZoom() }); } map.on('moveend', update); function createClusterIcon(feature, latlng) { if (!feature.properties.cluster) return L.marker(latlng); const count = feature.properties.point_count; const size = count < 100 ? 'small' : count < 1000 ? 'medium' : 'large'; const icon = L.divIcon({ html: `<div><span>${ feature.properties.point_count_abbreviated }</span></div>`, className: `marker-cluster marker-cluster-${ size}`, iconSize: L.point(40, 40) }); return L.marker(latlng, {icon}); } markers.on('click', (e) => { if (e.layer.feature.properties.cluster_id) { worker.postMessage({ getClusterExpansionZoom: e.layer.feature.properties.cluster_id, center: e.latlng }); } }); worker執行緒部分: importScripts('supercluster.min.js'); const now = Date.now(); let index; //getJSON('../test/fixtures/places.json', (geojson) => { getJSON('spotPoints.json', (geojson) => { //console.log(`loaded ${ geojson.length } points JSON in ${ (Date.now() - now) / 1000 }s`); console.log(`loaded ${ geojson.features.length } points JSON in ${ (Date.now() - now) / 1000 }s`); index = new Supercluster({ log: true, radius: 100,//60 extent: 256, maxZoom: 17//17 }).load(geojson.features); console.log(index.getTile(0, 0, 0)); postMessage({ready: true}); }); self.onmessage = function (e) { if (e.data.getClusterExpansionZoom) { postMessage({ expansionZoom: index.getClusterExpansionZoom(e.data.getClusterExpansionZoom), center: e.data.center }); } else if (e.data) { postMessage(index.getClusters(e.data.bbox, e.data.zoom)); } }; function getJSON(url, callback) { const xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.responseType = 'json'; xhr.setRequestHeader('Accept', 'application/json'); xhr.onload = function () { if (xhr.readyState === 4 && xhr.status >= 200 && xhr.status < 300 && xhr.response) { callback(xhr.response); } }; xhr.send(); }
- 完整的見原始碼demo下載,矢量瓦片實作部分思路:請求矢量資料源部分放在worker子執行緒處理,然后回傳來leaflet主執行緒來矢量瓦片渲染可視化,
主執行緒: //矢量瓦片 var vectorworker = new Worker('vectorGridworker.js'); vectorworker.onmessage = function (e) { //vectorworker.terminate(); if (e.data.type == "spot") {//圖斑 vectorGrid = L.vectorGrid.slicer(e.data.geojson, geojsonTileOptions).addTo(map); } else {//專案紅線 vectorRedGrid = L.vectorGrid.slicer(e.data.geojson, geojsonRedTileOptions).addTo(map); } }; worker執行緒: const now = Date.now(); let index; //getJSON('../test/fixtures/places.json', (geojson) => { getJSON('quanguoSpot.json', (geojson) => { //console.log(`loaded ${ geojson.length } points JSON in ${ (Date.now() - now) / 1000 }s`); console.log(`loaded ${ geojson.features.length } points JSON in ${ (Date.now() - now) / 1000 }s`); postMessage({type:"spot",geojson:geojson}); }); getJSON('quanguoRedLine.json', (geojson) => { //console.log(`loaded ${ geojson.length } points JSON in ${ (Date.now() - now) / 1000 }s`); console.log(`loaded ${ geojson.features.length } points JSON in ${ (Date.now() - now) / 1000 }s`); postMessage({type:"redline",geojson:geojson}); }); function getJSON(url, callback) { const xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.responseType = 'json'; xhr.setRequestHeader('Accept', 'application/json'); xhr.onload = function () { if (xhr.readyState === 4 && xhr.status >= 200 && xhr.status < 300 && xhr.response) { callback(xhr.response); } }; xhr.send(); }
完整demo原始碼見小專欄文章尾部:小專欄
文章尾部提供源代碼下載,對本專欄感興趣的話,可以關注一波
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/277306.html
標籤:GIS
