Leaflet を使ってみる

Leaflet という地図描画ライブラリ https://leafletjs.com/ を使って、地図上で次のようなことをやってみました。

* OpenStreetMap を表示する
* マーカーを置く
* マーカーをクリックしたときの説明・写真を追加する
* 円を描く
* 多角形を描く

上記のようなことであれば、短いコードで表現できるため便利だなと感じました。

ほんとうは、「あるエリア」(たとえば「北海道だけ」とか) を塗りつぶすというのがやりたかったのですが、今回はあきらめてます。ただ、「多角形を描く」の応用のような気がしますので、データさえそろえば達成できそうな感触はつかめました。

また、今回の記事は、次のサイトを参考にしました。大変わかりやすかったです。

* Leafletの使い方|オープンソースWeb地図ライブラリ|谷謙二研究室
http://ktgis.net/service/leafletlearn/index.html



# OpenStreetMap を表示する

OpenStreetMap https://www.openstreetmap.org/ は、地図データを供給してくれるサイト。Google Map の代替として最近よく目にします。

Leaflet 自体は地図データを持っていないので、OpenStreetMap を地図データの供給元として設定してみる、というのが以下のサンプルコードになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603093/456fe386-76c9-45ab-fd5c-3842c92423aa.png)

```html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.0/dist/leaflet.css" />
    <script src="https://unpkg.com/leaflet@1.3.0/dist/leaflet.js"></script>
    <script>
      function init() {
        //地図を表示するdiv要素のidを設定
        var map = L.map('mapcontainer', {zoomControl:false});
        // 縮尺表示
        L.control.scale({maxWidth:200,position:'bottomright',imperial:false}).addTo(map);
        // ズームコントロール (マウスのホイールコロコロがあれば不要。デフォルトは左上)
        L.control.zoom({position:'bottomleft'}).addTo(map);


        // オープンストリートマップ
        var osm = L.tileLayer('http://tile.openstreetmap.jp/{z}/{x}/{y}.png',
          {attribution: "<a href='http://osm.org/copyright' target='_blank'>OpenStreetMap</a> contributors" });
        osm.addTo(map);
        var mpoint = [50.086474, 14.411526]; // プラハ、カレル橋
        map.setView(mpoint, 15);
      }
    </script>
  </head>
  <body onload="init()">
    <div id="mapcontainer" style="position:absolute;top:0;left:0;right:0;bottom:0;"></div> <!-- ページに目いっぱい表示 -->
  </body>
</html>
```

# マーカーを置く

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603093/981d5468-f63d-fea5-6be8-a1243f706f59.png)

```javascript
        var mpoint = [50.086474, 14.411526]; // プラハ、カレル橋
        map.setView(mpoint, 15);

// ★ 以下を追記
        // クリック時の写真を追加 (写真データは tabinaka.co.jp から拝借)
        var pop1 = L.popup({maxWidth:550}).setContent(`カレル橋 (チェコ / プラハ)<br><img src="https://tabinaka.co.jp/magazine/wp-content/uploads/2019/09/shutterstock_369258188.jpg" style="width:240px;">`);
        L.marker(mpoint, {title:"カレル橋"}).bindPopup(pop1).addTo(map);
```

# 円や多角形を描く

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603093/9d37604b-b6b4-e261-bf3a-5b09d56d75c1.png)


```javascript
        L.marker(mpoint, {title:"カレル橋"}).bindPopup(pop1).addTo(map);

// ★ 以下を追記
        // 円を描く (赤の円。同心円で２つ。内側は「塗り」あり)
        L.circle(mpoint, { radius: 500, color: "red", fill: true, weight: 2 }).addTo(map);
        L.circle(mpoint, { radius: 1000, color: "red", fill: false, weight: 1 }).addTo(map);

        // 多角形を描く (正方形になるかな？と思ったけど、緯度が高いせいか縦長になっている。赤道付近で試すと正方形になった)
        var delta = 0.005;
        var arealatlons = [mpoint, [mpoint[0], mpoint[1]-delta], [mpoint[0]-delta, mpoint[1]-delta], [mpoint[0]-delta, mpoint[1]]];
        L.polygon(arealatlons, { color: 'blue', weight: 2, fill: true, fillColor: 'blue', opacity: 0.5 }).addTo(map);
```

# 完成版のソースコード全文

```html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.0/dist/leaflet.css" />
    <script src="https://unpkg.com/leaflet@1.3.0/dist/leaflet.js"></script>
    <script>
      function init() {
        //地図を表示するdiv要素のidを設定
        var map = L.map('mapcontainer', {zoomControl:false});
        // 縮尺表示
        L.control.scale({maxWidth:200,position:'bottomright',imperial:false}).addTo(map);
        // ズームコントロール (マウスのホイールコロコロがあれば不要。デフォルトは左上)
        L.control.zoom({position:'bottomleft'}).addTo(map);


        // オープンストリートマップ
        var osm = L.tileLayer('http://tile.openstreetmap.jp/{z}/{x}/{y}.png',
          {attribution: "<a href='http://osm.org/copyright' target='_blank'>OpenStreetMap</a> contributors" });
        osm.addTo(map);
        var mpoint = [50.086474, 14.411526]; // プラハ、カレル橋
        map.setView(mpoint, 15);

        // クリック時の写真を追加 (写真データは tabinaka.co.jp から拝借)
        var pop1 = L.popup({maxWidth:550}).setContent(`カレル橋 (チェコ / プラハ)<br><img src="https://tabinaka.co.jp/magazine/wp-content/uploads/2019/09/shutterstock_369258188.jpg" style="width:240px;">`);
        L.marker(mpoint, {title:"カレル橋"}).bindPopup(pop1).addTo(map);

        // 円を描く (赤の円。同心円で２つ。内側は「塗り」あり)
        L.circle(mpoint, { radius: 500, color: "red", fill: true, weight: 2 }).addTo(map);
        L.circle(mpoint, { radius: 1000, color: "red", fill: false, weight: 1 }).addTo(map);

        // 多角形を描く (正方形になるはずだけど、緯度が高いせいか縦長になっている。赤道付近で試すと正方形になった)
        var delta = 0.005;
        var arealatlons = [mpoint, [mpoint[0], mpoint[1]-delta], [mpoint[0]-delta, mpoint[1]-delta], [mpoint[0]-delta, mpoint[1]]];
        L.polygon(arealatlons, { color: 'blue', weight: 2, fill: true, fillColor: 'blue', opacity: 0.5 }).addTo(map);
      }
    </script>
  </head>
  <body onload="init()">
    <div id="mapcontainer" style="position:absolute;top:0;left:0;right:0;bottom:0;"></div> <!-- ページに目いっぱい表示 -->
  </body>
</html>
```

以上です。