leaflet如何加載10萬條數據

作爲一名GIS開發者,你工作中一定遇到過這種問題,根據業務設計,需要在地圖上添加1萬+條數據,數據或是點、或是線、或是面。但不管哪種,當你添加到5000條時,地圖操作就會出現明顯的卡頓。當你添加超過1萬條時,數據加載就會卡頓,瀏覽器出現卡死的狀態,地圖加載後,每挪動一下地圖,都要耐心的等待上幾秒鐘。

這種交互體驗,用戶是肯定接受不了的,解決方法通常分兩種,一種是去做深入的用戶需求分析,看用戶想一次性加載這麼多數據是爲了看什麼,想看的這個東西,通過其它技術方式能不能實現。另一種就是死磕技術,研究如何提升地圖性能。我們今天只討論第二種情況。

leaflet支持兩種渲染方式,svg 和 canvas,默認是svg渲染,這樣可以兼容低版本的IE瀏覽器。canvas渲染需要IE9+,或谷歌、火狐的高版本瀏覽器。canvas比svg性能好,我自己做了簡單的測試,svg模式加載5000個圖片標記時出現的卡頓情況,用canvas模式,加載10萬條數據時纔會出現。

下面講如何完全切換到canvas模式,共兩步:

一,在初始化地圖時,設置map的 preferCanvas 屬性爲 true,代碼如下:

var map = L.map('map', {
    center: [39.905963, 116.390813],
    zoom: 13,    
    preferCanvas: true
});

這個設置只針對繼承了Path類的矢量圖層有效,包括圓點(CircleMarker)、線(Polyline)、面(Polygon)、圓(Circle)、矩形(Rectangle)。針對圖片標記(Marker)沒有作用。
在這裏插入圖片描述

二、藉助插件 Leaflet.Canvas-Markers,提升Marker的顯示性能。插件git地址:https://github.com/eJuke/Leaflet.Canvas-Markers
在這裏插入圖片描述

Leaflet.Canvas-Markers 插件

Leaflet.Canvas-Markers 插件提供了一個 L.canvasIconLayer 類,這個類是一個圖層,將 Marker 添加到這個圖層中時,這個圖層會以 canvas 方式渲染 Marker 中的圖片。

如何使用

在html中引入插件

<script src="leaflet.canvas-markers.js"></script>

創建canvasIconLayer圖層,把圖層添加到地圖,給圖層添加圖片標記。

// 創建圖層,添加到 map
var ciLayer = L.canvasIconLayer({}).addTo(map);

// 定義 Marker
var marker =  L.marker([58.5578, 29.0087], {icon: icon});

// 把 Marker 添加到圖層
ciLayer.addMarker(marker);
注意

這個插件有個問題,就是地圖縮放時,添加的數據不跟着同步縮放,而是等到縮放完成後,再去縮放。這樣感覺縮放時,數據在飄着。
在這裏插入圖片描述

不過已經有人對這個問題提出瞭解決方案,並且解決了(鏈接),只是代碼一直沒有被合併。不過這都沒有關係,我們可以去用那份兒已經解決的代碼(鏈接

解決以後的效果:
在這裏插入圖片描述

完整代碼

注意;這份代碼因爲是引用的在線地址,所以存在上文中說的縮放地圖時感覺飄的問題,


<!DOCTYPE html>
<html>
<head>
  <title>leaflet-canvas-marker</title>
  <meta charset="utf-8" />
  <!-- 引入leafletapi -->
  <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" />
  <script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
  <!-- 引入leaflet-canvas-marker插件 -->
  <script src="https://unpkg.com/[email protected]"></script>
  <style>
    body { margin: 0; }
    .map {position: absolute; height: 100%; right: 0; left: 0; }
  </style>
</head>
<body>
  <div class="map" id="map"></div>
  <script>
    var map = L.map('map',{
      center: [39.905963, 116.390813],
      zoom: 14,
      preferCanvas: true    //使用canvas模式渲染矢量圖形 
    });
    //添加底圖
    var tiles = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png').addTo(map);
    //使用canvas模式渲染marker
    var ciLayer = L.canvasIconLayer({}).addTo(map);
    var icon = L.icon({
      iconUrl: 'https://ejuke.github.io/Leaflet.Canvas-Markers/examples/img/pothole.png',
      iconSize: [20, 18],
      iconAnchor: [10, 9]
    });
    for (var i = 0; i < 10000; i++) {
      var lat = 39.905963 + (Math.random()-Math.random()) * 3;
      var lng = 116.390813 + (Math.random()-Math.random()) * 3;
      var marker = L.marker([lat, lng], { icon: icon })
        .bindPopup("I Am " + i);    //綁定氣泡窗口
      ciLayer.addLayer(marker);
    }
    
  </script>
</body>
</html>


總結

  1. leaflet支持兩種渲染方式,svg 和 canvas,canvas的顯示性能要明顯優於svg。
  2. IE9之前版本瀏覽器不支持canvas方式渲染。
  3. 默認是svg方式渲染,要手動切換成canvas方式。
  4. 渲染方式設置成canvas後,加載矢量圖形性能會提升,加載圖片標記的效率仍然低。
  5. 通過Leaflet.Canvas-Markers插件來提升圖片標記的顯示效率。
  6. Leaflet.Canvas-Markers插件在縮放地圖時有bug,需要在github上找已經解決此bug的版本。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章