【Leaflet.js】住所から緯度経度を取得しその地点にピンを立てる


Leaflet.js はシンプルで拡張性の高いオープンソースの地図描画ライブラリです。
今回は Leaflet 地図に住所検索機能を追加してみたいと思います。

作りたいもの

  • 入力された住所から緯度経度を求める
  • 目的地点に地図の中心を移動
  • その地点にピンを立てて情報を表示
  • こんな感じのイメージ ↓

Leaflet 地図を準備

ファイル構成

.
├── index.html
└── main.js

index.html

  • leaflet.css と leaflet.js の読み込み順序に注意
  • 地図を描画する div 要素に対して width 属性を指定しないと表示されないので注意
index.html
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>住所検索</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/leaflet.min.css">
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/leaflet.min.js"></script>
    <style>
        #mymap {
            height: 500px;
            width: 500px;
        }
    </style>
</head>

<body>
    <input type="text" id="address" />
    <button id="search">検索</button>
    <div id="mymap"></div>
    <script type="module" src="./main.js"></script>
</body>

</html>

main.js

main.js
const map = L.map("mymap", {
    center: [35.021028, 135.755583],
    zoom: 15
});
const baseLayer = L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", {
    attribution: "&copy; <a href='https://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors'"
});
baseLayer.addTo(map);

住所の入力を受け付け緯度経度を求める

geolonia/normalize-japanese-addresses の紹介

住所から緯度経度を求めるのにはオープンソースの住所正規化ライブラリgeolonia/normalize-japanese-addressesを用います。

このライブラリは引数に与えた住所をパース・正規化した後、Geolonia 住所データに基づいてその地域の代表点の緯度経度を返します。

バージョン 2.3.0 から ES Modules 形式に対応されたようで、import 句を使って読み込むことができるようになりました。使用例を下に示します。

使用例
import { normalize } from 'https://cdn.skypack.dev/@geolonia/normalize-japanese-addresses';

normalize("滋賀県大津市御陵町3-1").then(result => {
    console.log(result);
});
出力
{
    pref: "滋賀県",
    city: "大津市",
    town: "御陵町",
    addr: "3-1",
    lat: 35.018665,
    lng: 135.855868,
    level: 3
}

Leaflet 地図にピンを立てる方法

bindPopupの引数には HTML タグを入れたりすることもできるのですが、詳細は割愛します。公式ドキュメントをご覧ください。

const latitude = 35.018665; // 緯度
const longitude = 135.855868; // 経度
const marker = L.marker([latitude, longitude]); // markerオブジェクトを作成
marker.bindPopup("大津市役所"); // markerをクリックしたとき"大津市役所"と表示されるようにする
marker.addTo(map); // markerをLeaflet地図に追加

あと、ピンを立てても表示範囲になければ変化がわかりませんので、ピンを立てると同時に地図の表示範囲もその地点に移動するようにしましょう。

map.flyTo([latitude, longitude]);

コードを組み立てる

最初に準備したコードを次のように書き換えます。

index.html

変更なし

main.js

main.js
import { normalize } from 'https://cdn.skypack.dev/@geolonia/normalize-japanese-addresses'

const map = L.map("mymap", {
    center: [35.021028, 135.755583],
    zoom: 15
});
const baseLayer = L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", {
    attribution: "&copy; <a href='https://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors'"
});
baseLayer.addTo(map);

// 以下を追加
document.getElementById("search").addEventListener("click", () => {
    const address = document.getElementById("address").value;
    normalize(address).then(result => {
        map.flyTo([result.lat, result.lng]); // 住所の地点に移動
        const marker = L.marker([result.lat, result.lng]); // ピンを作成
        marker.bindPopup(address); // ピンをクリックすると住所が表示されるようにする
        marker.addTo(map); // 地図にピンを立てる
    });
});

完成!

これでとりあえず動くものができました!

宣伝

本記事で作成したプログラムにエラー処理の追加やインターフェースの改良を施したものを Leaflet プラグインとして公開しました!

Cocon/Leaflet.CommunityGeoCoder

実際に触って動かせるデモページも作ってみました。ぜひご活用いただき、バグや機能提案などあればご気軽にお願いします。

Demo | Cocon/Leaflet.CommunityGeoCoder