勉強したことのメモ

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を用いてWeb上でマップ表示する方法

ゲーム攻略サイト等でゲーム内の地図をWeb上で表示し、マーカーを立てたりマウスホ ...

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

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

Leafletで「leaflet.sprite」プラグインを導入してマーカーの色を変更する方法

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

Leafletでマーカークリック時に当該マーカーをバウンド(跳ねる動作を)させる方法

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

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

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