🐥

google maps APIで大量にマーカーを配置する場合の最適化方法

2022/07/31に公開

始めに

google maps APIでmarkerを立てる場合、1000くらいならまだなんとかなりますが、5000くらいから大分重くなってしまいます。MarkerClustererでグループ化していても処理速度自体はそれほど変わらず重いままです。
色々調べても中々対策が見つからなかったのですが、それっぽい記事を見つけたのでそれベースで検証した内容を記事にしたいと思います。

https://tighten.com/blog/improving-google-maps-performance-on-large-datasets/

大量にマーカーを配置する場合の最適化方法

結論から言うと、画面に見えているところだけマーカーを設置するようにします。普通に書いていると見えていない部分もマーカーが配置されて計算されてしまうため、ズームやパン操作をしたときだけマーカーの再配置をします。

通常の配置

まず通常のサンプルを以下に示します。MarkerClustererにmakerを渡すと最初から全件マーカーを立ててくれて、楽ではありますが件数が増えるほど処理が重くなります。

const NUM_LOCATION = 1000;
const BASE_LAT = 35.6809591;
const BASE_LNG = 139.7673068;

const locations = _.times(NUM_LOCATION).map(() => {
  return {
    lat: BASE_LAT + (0.1 * Math.random() - 0.05),
    lng: BASE_LNG + (0.1 * Math.random() - 0.05),
  };
});

function initMap() {
  const map = new google.maps.Map(document.getElementById('map'), {
    zoom: 15,
    center: { lat: BASE_LAT, lng: BASE_LNG },
    gestureHandling: 'greedy',
    disableDefaultUI: true,
    clickableIcons: false,
  });
  
  const markers = locations.map((location) => {
    const marker = new google.maps.Marker({
      position: location,
    })
    return marker;
  });
  
  new markerClusterer.MarkerClusterer({ map, markers });
}

initMap();

見えているところだけmarkerを設置する

初期化時にmarkersは渡さず、必要なタイミングで画面に見えている部分だけマーカーを追加するように書き換えます。updateするタイミングが参考にした記事ではtilesloadedでしたが、そちらだとちょっとだけ移動したときだと更新されなくなってしまうので、dragendzoom_changedにしています。dragendの場合は慣性が効いて離した瞬間に更新すると期待する画面エリアからずれている時があったのでdebounceを入れています。

 function initMap() {
   // 省略
  
-  new markerClusterer.MarkerClusterer({ map, markers });
+  const clusterer = new markerClusterer.MarkerClusterer({ map });

+  const updateCluster = _.debounce(() => {
+    const bounds = map.getBounds();
+    clusterer.clearMarkers();
+    const visibleMarkers = markers.filter((marker) => {
+      return marker.getVisible() && bounds.contains(marker.getPosition());
+    });
+    clusterer.addMarkers(visibleMarkers);
+  }, 100);
  
+  map.addListener('dragend', updateCluster);
+  map.addListener('zoom_changed', updateCluster);
+  updateCluster();
 }

終わりに

以上がgoogle maps APIで大量にマーカーを配置する場合の最適化方法でした。これやっているだけで50000件とかにしても全然重たくならないので件数が多い場合は是非試してみると良いと思います。やっていることはシンプルですが意外と記事が見つからなかったのでこの記事が参考になれれば幸いです。
最後にサンプルも載せますので興味がある方は見てください。

Discussion