勉強したことのメモ

Webエンジニア / プログラマが勉強したことのメモ。

Leafletでマーカーをグループ化し、チェックボックスの状態により表示非表示を切り替える方法

  JavaScript

LeafletとOpenStreetMapでマップ上にマーカーを複数設置した上で、マーカーを「駅」「ビル」等のグループに所属させたい。また、マップ上にマーカーグループのチェックボックスを表示しチェックの有無で対応するマーカーの表示非表示を切り替えたい。以下にサンプル及びソースコードをメモ。

 

サンプル

https://taitan916.info/sample/leaflet.js/marker/toggle/

マップ左下に「駅」「寺」「その他」のチェックボックスがあり、チェックの有無で対応するマーカーの表示非表示が切り替えられる。

 

実装方法

ソースコード

<html lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Leafletでマーカーをグループ化し、チェックボックスの状態により表示非表示を切り替えるサンプル</title>
<style>
html, body, #map {
    height: 100%;
    margin: 0;
    padding: 0;
}
.menu{
    position: absolute;
    z-index: 500;
    width: 100px;
    bottom: 0;
    background-color: #fff;
}
</style>
</head>
<body>
    <div id="map"></div>
    <div class="menu">
        <div>
            <label>
                <input type="checkbox" class="menu_checkbox" onchange="changeMarker(this.checked, 1)">駅
            </label>
        </div>
        <div>
            <label>
                <input type="checkbox" class="menu_checkbox" onchange="changeMarker(this.checked, 2)">寺
            </label>
        </div>
        <div>
            <label>
                <input type="checkbox" class="menu_checkbox" onchange="changeMarker(this.checked, 3)">その他
            </label>
        </div>
    </div>

    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.css"/>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/leaflet-sprite@1.0.0/dist/leaflet.sprite.min.js"></script>
    <script type="text/javascript" src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
    <script>
    $(function(){
        $('.menu_checkbox').prop('checked',true); 
    });

    let map;
    map = L.map('map');

    //中心の経度緯度
    const center = ['35.681236', '139.767125'];

    //ズームレベル
    const zoom = 12;

    //マップの中心地とズームレベルを指定
    map.setView(center, zoom);

    const tileLayer = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',{
        attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a>',
        maxZoom: 19
    });
    tileLayer.addTo(map);

    //マーカー生成
    const mapData = [
        { 'lat' : '35.689607', 'lng' : '139.700571', 'body' : '新宿駅', 'category' : 1}, 
        { 'lat' : '35.681236', 'lng' : '139.767125', 'body' : '東京駅', 'category' : 1}, 
        { 'lat' : '35.628471', 'lng' : '139.73876', 'body' : '品川駅', 'category' : 1}, 
        { 'lat' : '35.714765', 'lng' : '139.796655', 'body' : '浅草寺', 'icon' : 'purple', 'category' : 2}, 
        { 'lat' : '35.658581', 'lng' : '139.745433', 'body' : '東京タワー', 'icon' : 'yellow', 'category' : 3}, 
        { 'lat' : '35.660238', 'lng' : '139.730077', 'body' : '六本木ヒルズ', 'icon' : 'yellow', 'category' : 3}, 
        { 'lat' : '35.636564', 'lng' : '139.763144', 'body' : 'レインボーブリッジ', 'icon' : 'yellow', 'category' : 3}, 
    ];
    var marker = [];
    for( key in mapData ){
        marker[key] = makeMarker(mapData[key]);
        marker[key].category = mapData[key].category;
    }

    //マーカー作成
    function makeMarker( mapData ){
        L.Icon.Default.imagePath = 'https://unpkg.com/leaflet@1.3.1/dist/images/';
        const icon = L.spriteIcon(mapData.icon);
        icon.options.popupAnchor = [2, -35];
        const marker = L.marker([mapData.lat, mapData.lng], {icon: icon})
        .bindPopup(mapData.body)
        .addTo(map);

        return marker;
    }

    //マーカーの表示切替
    function changeMarker( checked, category ){
        for( key in mapData ){
            if( mapData[key].category == category ){
                if( checked ){
                    marker[key] = makeMarker(mapData[key]);
                }else{
                    map.removeLayer(marker[key]);
                }
            }
        }
    }

    </script>
</body>
</html>

解説等

マップ生成時にグローバル変数のmarkerにマーカー情報を格納しておく。格納しておかないとマーカーの削除ができないっぽい(方法が見つからなかった)。

また、チェックボックス操作時にchangeMarker関数でマーカーの表示非表示を切り替えている。

 

所感

負荷の面で不安

やりたいことは実装できたもののchangeMarker関数を通すたびにマーカーの数だけループを回すことになるため、マーカーの数が多い場合に負荷がかかりそう。もっと効率の良い方法が見つけて改善したいところ。

 - JavaScript

  関連記事

Leafletにて地図を全画面(フルスクリーン)表示機能を追加する方法

Leafletにて表示されている地図に全画面表示ボタンが設置されているサイトがあ ...

leaflet.jsとOSMで現在地を取得しマップ上にマーカーを表示する方法

leaflet.jsとOpenStreetMapで現在位置の経度緯度を取得しマッ ...

Leafletで「leaflet-locatecontrol」プラグインを導入して現在地表示機能を追加する方法

LeafletとOpenStreetMapでマップ表示させ、特定のアイコンをクリ ...

Leafletで「Leaflet.markercluster」プラグインを導入してマーカークラスタ機能を追加する方法

LeafletとOpenStreetMapでマップ上にマーカーを複数設置した上で ...

Leafletで「leaflet-search」プラグインを導入してマーカーの検索機能を追加する方法

LeafletとOpenStreetMapでマップ上にマーカーを複数設置した上で ...