7.3 オンライン地図の利用

(1/1)
地図を見ている家族のイラスト
複数の WebAPI を組み合わせて新たなサービスを提供することをクラウド連携と呼ぶ。これまでの知識を総動員して、JavaScriptでクラウド連携プログラムを作ってみることにする。
指定した住所から最寄り駅を検索し、マップ上に表示することを目標にする。

目次

サンプル・プログラムの実行例

JavaScriptで最寄り駅を検索、マップに表示する

サンプル・プログラム

圧縮ファイルの内容
search_station.phpサンプル・プログラム本体。
pahooGeoCode.js住所・緯度・経度に関わるクラス pahooGeoCode。
使い方は「最寄り駅を求める」を参照。

要件定義

まず要件定義を明らかにしておこう。
  1. モダンブラウザおよびIEで動作すること。
  2. 無料で利用できること。
  3. マップを表示できること。
  4. 住所を入力し、対応する緯度・経度を検索できること。
  5. 緯度・経度の近くにある駅を検索できること。
  6. 検索した駅をマップ上に表示できること。
  7. 検索した駅を一覧表示できること。

使用するライブラリおよび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として表示することにする。

サンプル・プログラムの流れ

JavaScriptで最寄り駅を検索、マップに表示する
マップ描画、ジオコードに関わるメソッド、および検索結果を格納するプロパティは、再利用を考え、クラス pahooGeoCode に分離する。

メインプログラムでは、まず 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オブジェクト生成時に渡すこと。

  36: //グローバル変数:PGC
  37: let PGC = new pahooGeoCode('(取得したYahoo!APIキー)');

得られる緯度・経度は世界測地系(wgs84)であることに留意されたい。測地系については、「PHPの関数で複数の値を戻す - 測地系の違い」をご覧いただきたい。
WebAPIのURL
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として出力する際のコールバック関数名を入力するためのパラメータ。
応答データ構造(json) Feature Geometry Coordinates 経度,緯度 Type 図形種別 formatted_address 人間が読むことができる住所 address_component long_name 正式名称 short_name 略称 type 検索結果のタイプ geometry location lat 緯度 lng 経度

WebAPI の呼び出しと結果取得は「7.1 郵便番号→住所検索,Wikipedia検索」で説明したとおり。
非同期で結果を取得した後、サンプル・プログラムの流れに示したように、次に処理を渡さなければならない。そこで、結果を取得したらカスタムイベント 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)であることに留意されたい。
WebAPIのURL
URL
https://geoapi.heartrails.com/api/json?method=suggest

入力パラメータ
フィールド名 要否 内  容
method 必須 メソッド名:suggest(固定)
keyword 必須 検索キーワード(UTF-8でURLエンコード)
matching 必須 prefix(前方一致)、like(部分一致)、suffix(後方一致)のいずれか
jsonp 任意 JSONPとして出力する際のコールバック関数名を入力するためのパラメータ。
応答データ構造(json) response location city 市区町村名 city-kana 市区町村名よみ(平仮名) town 町域名 town-kana 町域名よみ(平仮名) x 経度(世界測値系) y 緯度(世界測値系) prefecture 都道府県名 postal 郵便番号(ハイフンなし)

WebAPI の呼び出しと、検索結果(JSONデータ)の処理(イベント)は、これまでと同様である。

「OSM Nominatim Search API」による緯度・経度変換

OSM Nominatim Search API」は、誰でも自由に地図を使えるよう、みんなでオープンデータの地理情報を作る「OpenStreetMap」(OSM)プロジェクトに含まれるWebAPIで、入力パラメータはGET渡しで、出力結果はJSONなどで戻すという形である。今回使う入力パラメータと出力結果のデータ構造を以下に示す。
得られる緯度・経度は世界測地系(wgs84)であることに留意されたい。
WebAPIのURL
URL
https://nominatim.openstreetmap.org/search

入力パラメータ
フィールド名 要否 内  容
format 任意 出力形式。html|xml|json|jsonv2。省略時はhtml
q 必須 住所やランドマーク(UTF-8)
json_callback 任意 json の出力をラップするコールバック関数(JSONP)
addressdetails 任意 住所の要素への細分化を含むかどうか。0|1。省略時は0
応答データ構造(json) place_id ID lon 経度(世界測値系) lat 緯度(世界測値系) display_name 住所,郵便番号など license ライセンス

WebAPI の呼び出しと、検索結果(JSONデータ)の処理(イベント)は、これまでと同様である。

HeartRails Geo API 最寄駅検索

HeartRails Geo API - 最寄駅情報取得 API」は、入力パラメータはGET渡しで、出力結果はJSONなどで戻すという形である。今回使う入力パラメータと出力結果のデータ構造を以下に示す。
WebAPIのURL
URL
https://express.heartrails.com/api/json

入力パラメータ
フィールド名 要否 内  容
method 必須 メソッド名:getStation(固定)
x 必須 最寄り駅を取得したい場所の経度(世界測地系)。
y 必須 最寄り駅を取得したい場所の緯度(世界測地系)。
(json) response station name 駅名 line 路線名 distance 検索地点からの距離 x 経度 y 緯度 prefecture 都道府県 postal 郵便番号 next 次の駅 prev 前の駅

WebAPI の呼び出しと、検索結果(JSONデータ)の処理(イベント)は、これまでと同様である。

コラム:Google Cloud Platform

Googleマップ
本文で触れた Google Cloud Platform は、Googleマップ以外にも様々な WebAPI を提供している。とくにジオコードは、住所だけでなく、駅やランドマークから緯度・経度を検索することができる強力なもので、世界中を検索対象としている。その分、マップを表示するより課金設定が高い。
ぱふぅ家のホームページでは、Googleマップが登場してすぐに利用を始めた。当時は無料だった。
測地系に揺らぎがあるなどの問題は徐々に改善されたが、途中、何度か WebAPI の仕様が変更になり、その都度対応しなければならなかった。
2018年6月に有料化し、同時に国内地図がゼンリンでなくなった。この影響は大きなものだったが、現時点でも無料枠内で利用を続けている。
さらにアクセス数が増えたら、今回利用している OpenStreetMap地理院地図 に乗り換えることになるだろう。

なお、今回利用した Leaflet からGoogleマップを利用することもできる。もちろん課金される。マップ右上の地図を選ぶメニューにGoogleマップが追加され、切り替えることができるようになる。
そのやり方は、「C++で直近の地震情報を取得する - マップを生成する」で紹介している。興味のある方はGoogleマップを利用できるよう改造してみてほしい。

参考サイト

(この項おわり)
header