LoginSignup
1
2

More than 3 years have passed since last update.

地図ライブラリ「Leaflet」のマーカー(アイコン)を変更するのに Canvas API を使う

Last updated at Posted at 2019-07-20

はじめに

地図ライブラリ「Leaflet」のマーカー(アイコン)を標準のマーカーからカスタムのものに変更するのに Canvas API を使う例を紹介します。
※Firefox Quantum 68 と Gooogle Chrome 71 で検証しました。

Canvas API を使おうと考えた背景

「Leaflet」のマーカーを変更する方法を検索すると、およそ、
1. アイコンの画像ファイルを用意する方法
2. プラグインを使用する方法
3. CSS を使用する方法
がヒットします。

私は手元の1個の html ファイルだけを編集してマーカーを変更する方法を模索していて、上記の中では 3. が該当します。

しかし、Canvas API を使えば 1. の方法の応用としても目的を果たせるのではないかと考えました。

表示例

See the Pen qedbEV by HideakiAnnaka (@HideakiAnnaka) on CodePen.

コード例

要点としては、
1. Canvas API でマーカーとなるアイコンの画像を描画
2. HTMLCanvasElement.toDataURL() メソッドで 1. の画像を表す DataURL を取得
3. Leaflet で地図を表示し、2. の DataURL をマーカーのアイコンの画像として指定
の 3 点になります。

sample.htm
<!DOCTYPE html>
<html>
    <head>
        <meta charset='UTF-8'>
        <title>地図ライブラリ「Leaflet」のマーカー(アイコン)を変更するのに Canvas API を使う</title>
        <link rel="stylesheet" href="https://unpkg.com/leaflet@1.5.1/dist/leaflet.css" 
            integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" 
            crossorigin=""/>
        <script src="https://unpkg.com/leaflet@1.5.1/dist/leaflet.js" 
            integrity="sha512-GffPMF3RvMeYyc1LWMHtK8EbPv0iNZ8/oTtHPx9/cc2ILxQ+u905qIwdpULaqDkyBKgOaB57QTMg7ztg8Jm2Og==" 
            crossorigin=""></script>
        <style>
        #canvas {
            display:none;
        }
        #mapid {
            width: 90vw;
            height: 90vh;
        }
        </style>
    </head>
    <body>
        <canvas id='canvas' width='25' height='41'></canvas>
        <div id="mapid"></div>
    </body>
    <script>
    {
        window.addEventListener('load', (event) => {
            init();
        });

        const init = () => {
            let canvasIconUrl = getCanvasIconUrl();

            let mymap = L.map('mapid').setView([35.360628, 138.727365], 12);

            L.tileLayer('https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png', {
                attribution: "<a href='https://maps.gsi.go.jp/development/ichiran.html' target='_blank'>地理院タイル</a>"
            }).addTo(mymap);

            const myIcon= L.icon({
                iconUrl: canvasIconUrl,
                shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.5.1/images/marker-shadow.png',
                iconSize: [25, 41],
                shadowSize: [41, 41],
                iconAnchor: [12.5, 41],
                popupAnchor: [0, -50],
            });

            L.marker([35.360628, 138.727365], {icon: myIcon}).addTo(mymap)
                .bindPopup('Canvas で描画したマーカーです。');
        }

        const getCanvasIconUrl = () => {
            const canvas = document.getElementById('canvas');
            if (canvas.getContext) {
                const ctx = canvas.getContext('2d');

                ctx.beginPath();
                ctx.arc(12.5, 12.5, 12.5, (Math.PI / 180) * 30, (Math.PI / 180) * 150, true);
                ctx.lineTo(12.5, 41);
                ctx.closePath();
                ctx.fillStyle = 'rgb(255, 102, 102)';
                ctx.fill();

                ctx.beginPath();
                ctx.arc(12.5, 12.5, 12, (Math.PI / 180) * 30, (Math.PI / 180) * 150, true);
                ctx.lineTo(12.5, 40.5);
                ctx.closePath();
                ctx.strokeStyle = 'rgb(102, 0, 51)';
                ctx.lineWidth = '1';
                ctx.stroke();

                ctx.beginPath();
                ctx.arc(12.5, 12.5, 5, (Math.PI / 180) * 0, (Math.PI / 180) * 360, true);
                ctx.closePath();
                ctx.fillStyle = 'rgb(102, 0, 51)';
                ctx.fill();

                return canvas.toDataURL();
            }
            else {
                return "https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.5.1/images/marker-icon.png";
            }
        }
    }
    </script>
</html>

参考記事

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2