Leafletで様々なマーカーを表示させる

# はじめに

こんにちは、開発部の一筒です！
Leaflet.jsに触れる機会があったので簡単にご紹介したいと思います。
様々な機能がありますが今回はマーカー(ピン)の様々な表示方法について書きます。



# Leafletとは
JavaScriptで書かれたオープンソースの地図描画ライブラリです。
地図をWebページに統合するために使用され、オープンソースで、使いやすいAPIを提供しています。
地図上にマーカー、ポップアップ、ポリライン、ポリゴンなどを描画し、ユーザーとの対話を可能にする機能を提供します。

https://leafletjs.com/




# まず地図を用意
Leafletを使用する前に地図を表示させます。地図にはOpenStreetMapを利用しました。

**OpenStreetMapとは**
フリーかつオープンソースの地図データベースです。
このデータベースは、世界中の道路、建物、公園、レストランなどの地理的な情報を含んでいます。
データはボランティアによって収集・編集され、誰でも利用できる形で提供されています。
OpenStreetMapはウェブベースの地図サービスだけでなく、様々なアプリケーションやプロジェクトで利用されています。

https://www.openstreetmap.org/about







最初に、OpenStreetMapとLeafletの利用に必要なCSSファイル、JavaScriptファイルをダウンロードまたはCDNから取得します。(OpenStreetMapについては省略しています。)

```html:マップの表示
<!-- Leaflet CSSファイルの読み込み -->
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<!-- Leaflet JavaScriptファイルの読み込み -->
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>

<!-- HTMLに地図を表示させるための要素を作成します。(サイズ指定が必要です。) -->
<div id="map" style="width:　500px;height:　300px;"></div>
```

次にLeafletを使用して地図を初期化し、OpenStreetMapレイヤーを追加します。

```javascript:マップの表示
// Leafletを使用して地図を初期化　初期の中心座標とズームレベルを指定
var map = L.map('map', {
    center: [34.693017433826746, 135.53148106698168],
    zoom: 17,
});

// OpenStreetMapレイヤーを追加、クレジット表記必須
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
    attribution: '© OpenStreetMap contributors'
}).addTo(map);
```

Leafletを使用して地図を初期化し、OpenStreetMapレイヤーを追加しています。
`L.tileLayer`のURLはOpenStreetMapのタイルサーバーからタイル画像を取得するためのもので、`{s}`、`{z}`、`{x}`、`{y}`などのプレースホルダーが使用されています。

指定した座標（34.693017433826746, 135.53148106698168）を中心にしたOpenStreetMapが表示されます。
![map_show.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3517332/733d1da5-4589-99fe-7210-e07d5073cfbe.png)


こんな感じで地図が表示されます。








# ピンの配置
![pin_many.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3517332/14ea6e50-5f41-79fe-0f09-12b27bf26100.png)



先ほど作成した`map`にマーカー(ピン)を配置します。複数配置可能です。

```javascript
L.marker([34.69388615509474, 135.53129439101346]).addTo(map);
L.marker([34.69287058455158, 135.53091819648327]).addTo(map);
```


- `L.marker([latitude, longitude])`:
新しいマーカーオブジェクト(ピン)を作成し、緯度と経度を指定します。
- `addTo(map)`:
マーカーオブジェクトを地図に追加します。










# クリックでピンを増やす
![pin_add.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3517332/ba1dcc84-e6d1-510f-23f6-113ff5baf0bf.gif)

クリックしてマーカーを増やしていく方法です。
値を取得してDBに保存したりも可能です。

```javascript
function onMapClick(e) {
    L.marker(e.latlng).addTo(map);
}
map.on('click', onMapClick);
```

- `e.latlng`: 
クリックが発生した位置の緯度と経度が格納されたオブジェクトです。
- `map.on('click', function(e) { })`: 
地図上でクリックが発生したときに実行されるイベントハンドラを設定します。
`click`の他に地図がズームされた時(`zoomend`)やドラッグされた時(`dragend`)に
イベントを発生させることも可能です。




# クリックするたびに移動
![pin_move.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3517332/73187c53-c5f1-f236-6653-74eab14d93bd.gif)

先ほどのコードを編集してクリックの度にマーカーを取り外し
移動させていく方法です。先ほどより表示がシンプルになります。

```javascript
var marker;
function onMapClick(e) {
    if (marker){
        map.removeLayer(marker);
    }
    marker = L.marker(e.latlng).addTo(map);
}
map.on('click', onMapClick);
```


- `map.removeLayer()`: 
マーカー、ポリライン、ポリゴンなど地図から指定されたレイヤーを削除するためのメソッドです。




# ポップアップ(吹き出し)を追加する
![map_popup.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3517332/3a8e06ed-1d9f-36f7-2fab-18b8f732f75e.png)
ポップアップは(吹き出し)テキストの他に画像を表示させることも可能です。
他にもカーソルを合わせると表示、クリックで表示などどのタイミングで表示させるのか変更も可能です。
```javascript
//文字のみの吹き出し
var marker = L.marker([34.694163, 135.531002]).addTo(map);
marker.bindPopup("　川",{autoClose:false}).openPopup();

//画像付きの吹き出し
var logo = "<img src={{ asset('/img/logo.png')}} >"
var popup = L.popup({ maxWidth: 550 }).setContent(logo);
var marker_2 = L.marker([34.693017433826746, 135.53148106698168]).addTo(map);
marker_2.bindPopup(popup,{autoClose:false}).openPopup();
```

- `bindPopup(content)`: 
マーカーにポップアップコンテンツを設定します。(`content`はポップアップに表示されるHTMLまたはテキストです。)
- `autoClose: false`：
autoCloseオプションは、ポップアップが開かれた時に、マップの他の部分がクリックされると自動的に閉じるかどうかを制御します。
(`false`で設定すると、ポップアップが開いたままになる)
- `openPopup()`：
ページを読み込んだと同時にポップアップを自動で開くためのメソッドです。
- `L.popup`：
新しいポップアップオブジェクトを作成します。このメソッドにはオプションを指定できます。
ここでは{ maxWidth: 550 }として最大幅を550pxに設定しています。
(ポップアップの横幅がこの値を超えないようにするため)

- `setContent(logo)`：
ポップアップの内容を指定します。





# プラグインや画像を使用して任意のピンに変更

![map_icon.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3517332/0de4f013-7cbd-8ef7-3d3e-bbcb1ef097d8.png)

```javascript
//leaflet.spriteを使用してカラーを変える
L.marker([34.693017433826746, 135.53148106698168],{icon: L.spriteIcon('green')}).addTo(map);

//Awesome-Markersを使用してアイコンをつける
options = {
    prefix: 'fa'
    ,icon: 'utensils'
    ,markerColor: 'blue'
};
L.marker([34.693300929887045, 135.5326475969532], {icon: L.AwesomeMarkers.icon(options)}).addTo(map);

//ピンを画像に変える    
var icon_ramen = L.icon({
  iconUrl:"{{ url('/img/ramen.png') }}",
  iconSize:[75,75],
  iconAnchor:[37,75],
  popupAnchor:[0,-70]
});
L.marker([34.69309942781918, 135.5337316601885],{icon:icon_ramen}).addTo(map);
```


- `L.icon({ iconUrl, iconSize, iconAnchor, popupAnchor })`: 
カスタムアイコンを作成します。
  - `iconUrl`: アイコンの画像のURL
  - `iconSize`: アイコンのサイズ
  - `iconAnchor`: アイコンのアンカーポイント（中心座標）
  - `popupAnchor`: ポップアップが表示される位置

- `L.marker([latitude, longitude], { icon: customIcon })`:
↑のカスタムアイコンを持つマーカーを作成します。





様々なプラグインが出ているので、マーカーの変更は自由自在です。

今回使用したプラグイン▼
leaflet.sprite：

https://github.com/leaflet-extras/leaflet.sprite

Awesome-Markers：

https://github.com/lennardv2/Leaflet.awesome-markers


他にCSSを当てることも可能です。
何を指しているマーカーなのかわかりやすくなりますね。






# さいごに
簡単ですがマーカー配置についてご紹介させていただきました。 
少しでもご参考になれば幸いです:fish_cake:

はつかぜ株式会社では、IT学習や業務に役立つ情報を定期的にお届けしていきたいと思っています。
システム開発のお問い合わせ・ご相談はこちら https://www.hatsukaze.co.jp/inquire/