目次
サンプル・プログラムの実行例
サンプル・プログラム
search_station.php | サンプル・プログラム本体。 |
pahooGeoCode.js | 住所・緯度・経度に関わるクラス pahooGeoCode。 使い方は「最寄り駅を求める」を参照。 |
要件定義
まず要件定義を明らかにしておこう。
- モダンブラウザおよびIEで動作すること。
- 無料で利用できること。
- マップを表示できること。
- 住所を入力し、対応する緯度・経度を検索できること。
- 緯度・経度の近くにある駅を検索できること。
- 検索した駅をマップ上に表示できること。
- 検索した駅を一覧表示できること。
使用するライブラリおよびWebAPI
マップ表示はGoogleマップが代表的であり、JavaScript向けのAPIも揃っており使い勝手がいい。しかし、Googleマップを含む Google Cloud Platform はAPIの利用量によって課金される。2021年9月現在、毎月200ドルまでは無料。個人で利用する分には無料枠で十分だろうが、今後無料枠の変更があるかもしれない。
そこで今回は、国土地理院の地理院地図や、オープンソースの世界地図作成プロジェクト「OpenStreetMap」を利用できる無償のJavaScriptライブラリ「Leaflet」を利用することにする。
住所から緯度・経度を検索を検索することをジオコードと呼ぶが、これを実現する WebAPI は幾つかある。今回は、「YOLPコンテンツジオコーダAPI」、「HeartRails Geo API - キーワードによる住所検索 API」「OSM Nominatim Search API」の3つから選べるようにする。いずれも無料の WebAPI だ。
緯度・経度から駅を検索できる WebAPI として、「HeartRails Geo API - 最寄駅情報取得API」を使うことにする。これも無料の WebAPI だ。
検索結果の最寄り駅は複数あり、Leflet にマーカー表示する。
一覧は、HTMLのTABLEとして表示することにする。
そこで今回は、国土地理院の地理院地図や、オープンソースの世界地図作成プロジェクト「OpenStreetMap」を利用できる無償のJavaScriptライブラリ「Leaflet」を利用することにする。
住所から緯度・経度を検索を検索することをジオコードと呼ぶが、これを実現する WebAPI は幾つかある。今回は、「YOLPコンテンツジオコーダAPI」、「HeartRails Geo API - キーワードによる住所検索 API」「OSM Nominatim Search API」の3つから選べるようにする。いずれも無料の WebAPI だ。
緯度・経度から駅を検索できる WebAPI として、「HeartRails Geo API - 最寄駅情報取得API」を使うことにする。これも無料の WebAPI だ。
検索結果の最寄り駅は複数あり、Leflet にマーカー表示する。
一覧は、HTMLのTABLEとして表示することにする。
サンプル・プログラムの流れ
マップ描画、ジオコードに関わるメソッド、および検索結果を格納するプロパティは、再利用を考え、クラス pahooGeoCode に分離する。
メインプログラムでは、まず draw_leaflet メソッドを使ってマップを描く。まだ情報が無いのでマーカーは表示しない。
検索ボタンが押下されたら、入力値(query)があれば、geocode メソッドを使って、対応する緯度・経度を検索する。geocodeメソッド は、引数 api の値に応じて、前述の3つの ジオコードWebAPI のいずれかを呼び出す。
これまで学んできたように、WebAPI 呼び出しは非同期で行われる。検索結果が返ってきたらプロパティpdataに代入し、カスタムイベント geocode を発生させる。
入力値(query)が無い、またはカスタムイベント geocode をキャッチしたら、search_station メソッドを使って、緯度・経度から最寄り駅を検索する。これも非同期で行われるから、検索結果が返ってきたらプロパティpdataに代入し、カスタムイベント station を発生させる。
カスタムイベント station をキャッチしたら、del_marker2leaflet で表示中のマーカーを全て削除し、あらたに marker2leaflet を使ってマップ上に駅の位置を表すマーカーを追加する。そして、一覧表示を行う。
メインプログラムでは、まず draw_leaflet メソッドを使ってマップを描く。まだ情報が無いのでマーカーは表示しない。
検索ボタンが押下されたら、入力値(query)があれば、geocode メソッドを使って、対応する緯度・経度を検索する。geocodeメソッド は、引数 api の値に応じて、前述の3つの ジオコードWebAPI のいずれかを呼び出す。
これまで学んできたように、WebAPI 呼び出しは非同期で行われる。検索結果が返ってきたらプロパティpdataに代入し、カスタムイベント geocode を発生させる。
入力値(query)が無い、またはカスタムイベント geocode をキャッチしたら、search_station メソッドを使って、緯度・経度から最寄り駅を検索する。これも非同期で行われるから、検索結果が返ってきたらプロパティpdataに代入し、カスタムイベント station を発生させる。
カスタムイベント station をキャッチしたら、del_marker2leaflet で表示中のマーカーを全て削除し、あらたに marker2leaflet を使ってマップ上に駅の位置を表すマーカーを追加する。そして、一覧表示を行う。
YOLPコンテンツジオコーダAPI
「YOLPコンテンツジオコーダAPI」は、入力パラメータはGET渡しで、出力結果はJSONなどで受け取る WebAPI である。今回使う入力パラメータと出力結果のデータ構造を以下に示す。
利用料は無料だが、Yahoo!JAPAN ID が必要となる。「各種WebAPIの登録方法 - Yahoo!JAPAN デベロッパーネットワーク」をご覧いただきたい。
取得した APIキー は次のように、pahooGeoCodeオブジェクト生成時に渡すこと。
利用料は無料だが、Yahoo!JAPAN ID が必要となる。「各種WebAPIの登録方法 - Yahoo!JAPAN デベロッパーネットワーク」をご覧いただきたい。
取得した APIキー は次のように、pahooGeoCodeオブジェクト生成時に渡すこと。
36: //グローバル変数:PGC
37: let PGC = new pahooGeoCode('(取得したYahoo!APIキー)');
得られる緯度・経度は世界測地系(wgs84)であることに留意されたい。測地系については、「PHPの関数で複数の値を戻す - 測地系の違い」をご覧いただきたい。
URL |
---|
https://map.yahooapis.jp/geocode/cont/V1/contentsGeoCoder |
フィールド名 | 要否 | 内 容 |
---|---|---|
appid | 必須 | アプリケーションID |
query | 必須 | 住所やランドマーク |
ei | 任意 | 文字エンコード:UTF-8(デフォルト)/EUC-JP/SJISなど |
category | 任意 | 検索対象カテゴリ:address(デフォルト)/landmark/world |
results | 任意 | 表示件数:最大10(デフォルト) |
output | 任意 | 出力形式:json/xml |
callback | 任意 | JSONPとして出力する際のコールバック関数名を入力するためのパラメータ。 |
WebAPI の呼び出しと結果取得は「7.1 郵便番号→住所検索,Wikipedia検索」で説明したとおり。
非同期で結果を取得した後、サンプル・プログラムの流れに示したように、次に処理を渡さなければならない。そこで、結果を取得したらカスタムイベント geocode を発生させ、メインプログラム側で、このイベントをキャッチすることにした。
カスタムイベントを発生させるために、CustomEvent インターフェースが用意されている。
CustomEventコンストラクタ は第1引数にイベント名を、第2引数にイベント発生時に渡すオブジェクトを記述する。このオブジェクトは、detail を要素名とすると決められている。
インターフェースの用意ができたら、dispatchEvent メソッドでイベントを発生させる。
非同期で結果を取得した後、サンプル・プログラムの流れに示したように、次に処理を渡さなければならない。そこで、結果を取得したらカスタムイベント geocode を発生させ、メインプログラム側で、このイベントをキャッチすることにした。
カスタムイベントを発生させるために、CustomEvent インターフェースが用意されている。
CustomEventコンストラクタ は第1引数にイベント名を、第2引数にイベント発生時に渡すオブジェクトを記述する。このオブジェクトは、detail を要素名とすると決められている。
インターフェースの用意ができたら、dispatchEvent メソッドでイベントを発生させる。
10: //IE用CustomEvent
11: if (document.documentMode) {
12: ! function () {
13: let prototype = CustomEvent.prototype
14: function CustomEvent(type, option) {
15: let eve = document.createEvent('Event')
16: option = option || {}
17: eve.initEvent(type, !!option.bubbles, !!option.cancelable)
18: return eve
19: }
20: CustomEvent.prototype = prototype
21: window.CustomEvent = CustomEvent
22: }();
23: }
IEには CustomEventインターフェース が無いため、別途用意した。
「HeartRails Geo API」による緯度・経度変換
「HeartRails Geo API - キーワードによる住所検索 API」は、入力パラメータはGET渡しで、出力結果はJSONなどで戻すという形である。今回使う入力パラメータと出力結果のデータ構造を以下に示す。
得られる緯度・経度は世界測地系(wgs84)であることに留意されたい。
得られる緯度・経度は世界測地系(wgs84)であることに留意されたい。
URL |
---|
https://geoapi.heartrails.com/api/json?method=suggest |
フィールド名 | 要否 | 内 容 |
---|---|---|
method | 必須 | メソッド名:suggest(固定) |
keyword | 必須 | 検索キーワード(UTF-8でURLエンコード) |
matching | 必須 | prefix(前方一致)、like(部分一致)、suffix(後方一致)のいずれか |
jsonp | 任意 | JSONPとして出力する際のコールバック関数名を入力するためのパラメータ。 |
WebAPI の呼び出しと、検索結果(JSONデータ)の処理(イベント)は、これまでと同様である。
「OSM Nominatim Search API」による緯度・経度変換
「OSM Nominatim Search API」は、誰でも自由に地図を使えるよう、みんなでオープンデータの地理情報を作る「OpenStreetMap」(OSM)プロジェクトに含まれるWebAPIで、入力パラメータはGET渡しで、出力結果はJSONなどで戻すという形である。今回使う入力パラメータと出力結果のデータ構造を以下に示す。
得られる緯度・経度は世界測地系(wgs84)であることに留意されたい。
得られる緯度・経度は世界測地系(wgs84)であることに留意されたい。
URL |
---|
https://nominatim.openstreetmap.org/search |
フィールド名 | 要否 | 内 容 |
---|---|---|
format | 任意 | 出力形式。html|xml|json|jsonv2。省略時はhtml |
q | 必須 | 住所やランドマーク(UTF-8) |
json_callback | 任意 | json の出力をラップするコールバック関数(JSONP) |
addressdetails | 任意 | 住所の要素への細分化を含むかどうか。0|1。省略時は0 |
WebAPI の呼び出しと、検索結果(JSONデータ)の処理(イベント)は、これまでと同様である。
HeartRails Geo API 最寄駅検索
「HeartRails Geo API - 最寄駅情報取得 API」は、入力パラメータはGET渡しで、出力結果はJSONなどで戻すという形である。今回使う入力パラメータと出力結果のデータ構造を以下に示す。
URL |
---|
https://express.heartrails.com/api/json |
フィールド名 | 要否 | 内 容 |
---|---|---|
method | 必須 | メソッド名:getStation(固定) |
x | 必須 | 最寄り駅を取得したい場所の経度(世界測地系)。 |
y | 必須 | 最寄り駅を取得したい場所の緯度(世界測地系)。 |
WebAPI の呼び出しと、検索結果(JSONデータ)の処理(イベント)は、これまでと同様である。
コラム:Google Cloud Platform
本文で触れた Google Cloud Platform は、Googleマップ以外にも様々な WebAPI を提供している。とくにジオコードは、住所だけでなく、駅やランドマークから緯度・経度を検索することができる強力なもので、世界中を検索対象としている。その分、マップを表示するより課金設定が高い。
ぱふぅ家のホームページでは、Googleマップが登場してすぐに利用を始めた。当時は無料だった。
測地系に揺らぎがあるなどの問題は徐々に改善されたが、途中、何度か WebAPI の仕様が変更になり、その都度対応しなければならなかった。
2018年6月に有料化し、同時に国内地図がゼンリンでなくなった。この影響は大きなものだったが、現時点でも無料枠内で利用を続けている。
さらにアクセス数が増えたら、今回利用している OpenStreetMap か 地理院地図 に乗り換えることになるだろう。
なお、今回利用した Leaflet からGoogleマップを利用することもできる。もちろん課金される。マップ右上の地図を選ぶメニューにGoogleマップが追加され、切り替えることができるようになる。
そのやり方は、「C++で直近の地震情報を取得する - マップを生成する」で紹介している。興味のある方はGoogleマップを利用できるよう改造してみてほしい。
測地系に揺らぎがあるなどの問題は徐々に改善されたが、途中、何度か WebAPI の仕様が変更になり、その都度対応しなければならなかった。
2018年6月に有料化し、同時に国内地図がゼンリンでなくなった。この影響は大きなものだったが、現時点でも無料枠内で利用を続けている。
さらにアクセス数が増えたら、今回利用している OpenStreetMap か 地理院地図 に乗り換えることになるだろう。
なお、今回利用した Leaflet からGoogleマップを利用することもできる。もちろん課金される。マップ右上の地図を選ぶメニューにGoogleマップが追加され、切り替えることができるようになる。
そのやり方は、「C++で直近の地震情報を取得する - マップを生成する」で紹介している。興味のある方はGoogleマップを利用できるよう改造してみてほしい。
参考サイト
- Leaflet
- YOLPコンテンツジオコーダAPI
- HeartRails Geo API
- OSM Nominatim Search API
- 各種WebAPIの登録方法:ぱふぅ家のホームページ
- PHPで住所・ランドマークから緯度・経度を求める:ぱふぅ家のホームページ
- PHPで住所・ランドマークから最寄り駅を求める:ぱふぅ家のホームページ
- C++ で最寄駅を検索:ぱふぅ家のホームページ
(この項おわり)
指定した住所から最寄り駅を検索し、マップ上に表示することを目標にする。