【Leaflet/leaflet-heat.js】ヒートマップを表示する

ネコニウム研究所

PCを利用したモノづくりに関連する情報や超個人的なナレッジを掲載するブログ

【Leaflet/leaflet-heat.js】ヒートマップを表示する

2023-6-29 | ,

Leafletでleaflet-heat.jsを使ってヒートマップを表示したい!

概要

今回の記事では、Leafletでleaflet-heat.jsを使ってヒートマップを表示する手順を掲載する。

仕様書

環境

  • Leaflet 1.7.1
  • Leaflet.heat 0.2.0

手順書

今回は、leaflet-heat.jsを使ってマップの上にヒートマップを表示する。

柱の位置にデータを設定したサンプル。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8" />
    <title>Leaflet Test</title>
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" />
    <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>
    <script src="https://cdn.rawgit.com/Leaflet/Leaflet.heat/gh-pages/dist/leaflet-heat.js"></script>
    <script>
        function init() {
            var lat2xy = function (x, y) {
                return map.project([x, y], map.getMaxZoom());
            };

            var image = {
                url: "https://blog.nekonium.com/wp-content/uploads/catacombs_of_the_cursed_witch.png",
                width: 2030,
                height: 2730,
            };

            var map = L.map("leaflet-container", {
                crs: L.CRS.Simple,
                minZoom: -1,
                maxZoom: 4,
            });

            var imageBounds = L.latLngBounds([map.unproject([0, image.height], map.getMaxZoom()), map.unproject([image.width, 0], map.getMaxZoom())]);

            map.fitBounds(imageBounds);
            map.setMaxBounds(imageBounds.pad(0.5));

            L.imageOverlay(image.url, imageBounds).addTo(map);

            var heatDataPixels = [
                [140, 560, 1],
                [140, 630, 1],
                [210, 560, 1],
                [210, 630, 1],
                [1120, 140, 1],
                [1120, 210, 1],
                [1190, 140, 1],
                [1190, 210, 1],
                [1830, 850, 1],
                [1870, 930, 1],
                [1950, 975, 1],
                [2045, 975, 1],
                [2120, 930, 1],
                [2165, 850, 1],
                [2165, 760, 1],
                [2120, 680, 1],
                [2045, 635, 1],
                [1950, 635, 1],
                [1870, 680, 1],
                [1830, 760, 1]
            ];

            var heatData = heatDataPixels.map(function (point) {
                var latLng = map.unproject([point[1], point[0]], map.getMaxZoom());
                return [latLng.lat, latLng.lng, point[2]];
            });

            var heat = L.heatLayer(heatData, { radius: 25 }).addTo(map);
        }
    </script>
</head>
<body onload="init()">
    <div id="leaflet-container" style="position: absolute; top: 0; left: 0; right: 0; bottom: 0"></div>
</body>
</html>

解説

下記のようなN x 3の2次配列でヒートマップのデータを作る。

var heatDataPixels = [
                [140, 560, 1],
                [140, 630, 1],
                [210, 560, 1],
                [210, 630, 1],
                [1120, 140, 1],
                [1120, 210, 1],
                [1190, 140, 1],
                [1190, 210, 1],
                [1830, 850, 1],
                [1870, 930, 1],
                [1950, 975, 1],
                [2045, 975, 1],
                [2120, 930, 1],
                [2165, 850, 1],
                [2165, 760, 1],
                [2120, 680, 1],
                [2045, 635, 1],
                [1950, 635, 1],
                [1870, 680, 1],
                [1830, 760, 1]
            ];

配列の要素の内訳。

[Y座標, X座標, 輝度(0.0~1.0)]

これを座標分作る。

今回はカスタムイメージのマップなので座標はピクセル座標なんだけども、leaflet-heat.jsでは緯度経度を使うので座標を変換する必要がある。

変換するコード。

            var heatData = heatDataPixels.map(function (point) {
                var latLng = map.unproject([point[1], point[0]], map.getMaxZoom());
                return [latLng.lat, latLng.lng, point[2]];
            });

ヒートマップのデータをheatLayerのコンストラクターに渡す。

            var heat = L.heatLayer(heatData, { radius: 25 }).addTo(map);

radiusオプションは座標1つ分が影響する範囲を半径で設定できる。

デモ

CODEPENで動かしてみると下記のような感じ。

See the Pen
Leaflet Heatmap Test
by 108nen (@108nen)
on CodePen.

まとめ(感想文)

ヒートマップでいろいろ可視化できそう!