BODIK APIの使い方(Javascript編)機能追加2

BODIK APIの使い方(Javascript編)」で、Javascriptを使ったWebアプリケーションで、BODIK APIをどのように使うのかをご説明しています。課題2では、BODIK APIを呼び出した結果を地図に表示するプログラムを記述しました。

課題2のプログラムに機能を追加することを考えてみましょう。

検索領域を円で表示する

課題2のプログラムでは、地図をクリックすると、そのクリックされた地点を中心に一定の半径内にある「AED」をBODIK APIで検索し、その結果を地図上にマーカーとして表示しました。この中心点と半径の関係が地図に表示できていません。

イメージとしては、クリックされた地点を中心に円を表示したいところです。

対策

基本的な考え方として、次のようになります。

  1. 古い円があったら削除する。
  2. クリックされた地点を中心に指定された半径の円を描く。

「円を描く」は、Leafletの「circle」が使えます。

let circle = L.circle([lat, lon] , options);
circle.addTo(map);

「円を削除する」は、Leafletの「removeLayer」メソッドを使えます。

map.removeLayer(circle);

プログラムは次のようになります。

半径(distance=20000)が大きすぎたので、2000mに変更しました。

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <title>BODIK API</title>
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
        integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
        crossorigin="" />
    <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
        integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="
        crossorigin=""></script>

    <script type="text/javascript">
        let map = null;
        let marker_list = null;    // マーカーの配列
        let marker_layer = null;   // マーカーのレイヤー
        let areaCircle = null;     // 領域を示す円
        function init() {
            map = L.map('map', { zoomControl: false });
            //  指定された緯度経度を中心とした地図
            let lat = 33.59334325082392;
            let lon = 130.35598920962553;
            let center = [lat, lon];
            map.setView(center, 14);

            //地理院地図の標準地図タイル
            let gsi = L.tileLayer('https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png',
                { attribution: "<a href='https://maps.gsi.go.jp/development/ichiran.html' target='_blank'>地理院タイル</a>" });
            gsi.addTo(map);

            //showMarker(lat, lon);
            map.on('click', onMapClick);
        }

        function onMapClick(e) {
            let latlng = e.latlng;
            let lat = latlng.lat;
            let lon = latlng.lng;
            showMarker(lat, lon);
        }

        function showMarker(lat, lon) {
            let api_server = 'https://wapi.bodik.jp';
            let api = 'aed';
            let distance = 2000;
            let maxResults = 100;
            let api_url = `${api_server}/${api}?select_type=geometry&lat=${lat}&lon=${lon}&distance=${distance}&maxResults=${maxResults}`;
            fetch(api_url)
            .then(response => response.json())
            .then(data => {
                if (marker_layer) {                    // 古いレイヤがあったら
                    map.removeLayer(marker_layer);     // レイヤーを削除する 
                    marker_layer = null;
                }
                // 検索領域を示す
                if (areaCircle) {                      // 古い円があったら
                    map.removeLayer(areaCircle);       // 削除する
                    areaCircle = null;
                }
                //  クリックされた地点を中心に円を描く
                areaCircle = L.circle([lat, lon],
                    {
                        radius: distance,
                        color: '#5555ff',
                        weight: 1,
                        fill: true,
                        opacity: 0.5
                    }
                );
                areaCircle.addTo(map);

                let features = data['resultsets']['features'];
                marker_list = [];
                for (let feature of features) {
                    let properties = feature['properties'];
                    let popup = L.popup().setContent(properties['name']);

                    let geometry = feature['geometry'];
                    let location = geometry['coordinates'];
                    let marker = L.marker([location[1], location[0]]);
                    marker.bindPopup(popup);
                    marker_list.push(marker);         // 配列に記録する
                }

                if (marker_list.length > 0) {
                    marker_layer = L.layerGroup(marker_list);   // レイヤーを作成
                    map.addLayer(marker_layer);                 // 地図に表示する
                }
            });
        } 
    </script>

</head>

<body onload="init()">
    <h2>BODIK API program #2</h2>
    <div class="map" id="map" style="width:800px;height:600px"></div>
</body>

</html>

どの範囲を検索した結果を表示しているのか?がわかるようになりましたね。

ひらの