JavaScript 地図ライブラリ Leaflet 基本処理サンプル

# 初めに
JavaScript地図ライブラリのLeafletの基本処理サンプル
良く忘れるのでメモ

## フォルダ構成

```
├─ index.html
└─ assets
    ├─ icon
    │   ├─ current.png
    │   └─ point.png
    └─ js
        └─ leaflet_common.js
```
※画像も用意する必要あり

## JavaScript（処理共通）
``` javascript:leaflet_common.js
// *******************************************
// Leaflet共通処理
// 地図表示、アイコン表示、表示アイコン初期化
// ※注意書き
// 　オープンストリートマップを使っている(国土地理院を使う場合はリンク先を変更する必要あり)
//   varになっているmapObj、putIconsObjについては、画面上で操作する必要あり
// *******************************************

// マップオブジェクト
var mapObj = null;
// 地図のリンク先
const MAP_LINK = '<a href="http://openstreetmap.org">OpenStreetMap</a>';
// 地図のタイルＵＲＬ
const MAP_TILE = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'

// 初期のズーム値(小さいほうが引き)
const START_ZOOM = 15;
// 最大のズーム値
const MAX_ZOOM = 20;
// 最大のズーム値
const ICON_FOLDER = "./assets/icon/";
// アイコンのファイルパス定義
const ICON_IMAGE = {
    0: "current.png",
    1: "point.png",
}
// アイコンのサイズ
const ICON_SIZE = 36;
// アイコンオブジェクト
var putIconsObj = [];
// 現在地アイコンオブジェクト
var currentIconObj = [];


// --------------------------------------------
// 地図表示関数
// cur_lat_t : 表示する中心緯度
// cur_lng_t : 表示する中心経度
// --------------------------------------------
const viewMap = function(cur_lat_t, cur_lng_t){

    // マップオブジェクトに設定現在地と初期ズーム値を設定
    mapObj = L.map('map_area').setView([cur_lat_t, cur_lng_t], START_ZOOM);
    // 地図表示情報を設定
    L.tileLayer(
        MAP_TILE,
        {
            attribution: 'Map data &copy; ' + MAP_LINK, // リンク元
            maxZoom: MAX_ZOOM                           // 最大ズーム値
        }
    ).addTo(mapObj);
};

// --------------------------------------------
// １つのアイコンを表示する
//  lat_t:表示緯度
//  lng_t:表示経度
//  imgIdx:アイコン画像のインデックス(ICON_IMAGE参照)
//  popup_value:ポップアップ表示内容
//  iconSize:アイコンのサイズ / 形式は [横, 縦] で指定
// --------------------------------------------
const putIcon = function(lat_t=0.0, lng_t=0.0, imgIdx=0, popup_value=null, iconSize=[ICON_SIZE, ICON_SIZE]){

    // アイコン情報を設定取得
    var pointIcon = L.icon({
        iconUrl: ICON_FOLDER + ICON_IMAGE[imgIdx], // 画像のＵＲＬ
        iconSize: iconSize,                        // アイコンサイズ
    });

    // 取得するアイコンオブジェクト
    let iconObj = null;
    // アイコン設定
    iconObj = L.marker([lat_t, lng_t], {icon: pointIcon}).addTo(mapObj);
    // ポップアップがある場合
    if(popup_value){
        // ポップアップ内容をアイコンに設定
        iconObj.bindPopup(popup_value);
        // アイコンにポップアップイベントを設定
        iconObj.on("click", function(){
            this.openPopup();
        });
    }
    return iconObj;
};

// --------------------------------------------
// 地図上のアイコンを初期化(アイコンを再表示する際などに使用)
// --------------------------------------------
const dropIcons = function(){
    if(putIconsObj.length){
        // 地図上のアイコンを初期化
        for(idx in putIconsObj){
            // 地図上から表示を外す
            mapObj.removeLayer(putIconsObj[idx]);
            // ポップアップイベントをオフにする
            putIconsObj[idx].off("click");
        }
    }
    // アイコンオブジェクト配列を初期化
    putIconsObj = [];
}
``` 

### HTML（使い方）
``` html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<meta http-equiv="content-language" content="ja">
<title>Leaflet サンプル</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" />
<style>
    /* ページ全体 */
    html, body  {
        width: 100vw;
        height: 100vh;
        padding: 0px;
        margin: 0px;
    }
    /* 地図領域（サイズはお好みで） */
    #map_area {
        width: 100%;
        height: 100%;
    }
</style>
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>
<script src="assets/js/leaflet_common.js"></script>
<script>
    // 場所情報(仮作成＠博多近辺)
    var tempPlaceData = [
        {"id":"1", "lat": 33.59513931435894,  "lng": 130.42419433593753, "name":"地点Ａ"},
        {"id":"2", "lat": 33.59260123175435,  "lng": 130.41131973266604, "name":"地点Ｂ"},
        {"id":"3", "lat": 33.59517506146791,  "lng": 130.42694091796878, "name":"地点Ｃ"},
        {"id":"4", "lat": 33.59653344063089,  "lng": 130.420138835907,   "name":"地点Ｄ"},
        {"id":"5", "lat": 33.590813804823924, "lng": 130.42249917984012, "name":"地点Ｅ"},
        {"id":"6", "lat": 33.590849553725455, "lng": 130.4186797142029,  "name":"地点Ｆ"},
    ];

    // 画面初期表示時
    window.onload = function(){
        // 緯度経度取得関数(引数は下記の事後処理)
        navigator.geolocation.getCurrentPosition(gcpAfterFunc);
    };

    // 座標取得後の初期処理
    const gcpAfterFunc = function(position){

        // データ取得関数(可変の場合は、ajax処理等で取ってくる)
        let placeData = tempPlaceData;

        //緯度経度取得
        let lat_t = position.coords.latitude;
        let lng_t = position.coords.longitude;

        //地図表示関数
        viewMap(lat_t, lng_t);

        // 地図のイベント処理は、このタイミングで指定
        mapObj.on('click', testfunc);

        // アイコン表示
        putIconsData(placeData, 1);

        // 現在地のアイコンを表示し、オブジェクトを取得
        currentIconObj = putIcon(lat_t, lng_t, 0);

    }

    // 渡されたjsonデータのアイコンを表示する(サンプルでは、戻り値での判定は行っていない)
    const putIconsData = function(jsonData, imgIdx = 0){
        // 処理されたか
        let isProcessed = false;

        // インデックスに対する画像がある場合は実行
        if(ICON_IMAGE[imgIdx]){

            for(var idx in jsonData){
                // アイコンを地図上に設定、ポップアップで地点名を設定し、オブジェクトとして取得、
                putIconsObj[idx] = putIcon(jsonData[idx]["lat"], jsonData[idx]["lng"], imgIdx, jsonData[idx]["name"]);
                // ※ポップアップ表示したい場合やアイコンサイズを変えたい場合は以下のように指定
                // putIconsObj[idx] = putIcon(jsonData[idx].lat, jsonData[idx].lng, imgIdx, jsonData[idx]["name"], [36, 48]);

                // 実行した場合はtrueとする
                if(!isProcessed) isProcessed = true;
            }
        }

        // ループで処理がされている場合は、trueを返す
        return isProcessed;
    }

    // テスト関数
    const testfunc = function(e){

        let lat_t = e.latlng.lat;
        let lng_t = e.latlng.lng;

        console.log([lat_t, lng_t]);
    }
</script>
</head>
<body>
    <div id="map_area"></div>
</body>
</html>

``` 
※専用のcssとjsは読み込む必要あり
※上記のjsも読み込む必要あり


## 画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/541739/2f9fb40d-df51-280d-229e-5ade149e7c98.png)
※chromeのスマホデバッグ

## あとがき
引数で初期値を設定しているため、ＩＥでは動きません。