「みんなでテイクアウトMAP」を例に説明
- 「テイクアウト」とあるけど、別に「トイレ」でも「酒屋」でもOK
- データソースはOpenStreetMap。オープンデータで登録不要のAPIがあるので便利
- 自前でデータベースと中に入れるデータを整備するよりも遥かに効率的
- 不足したデータはみんなで登録することで、他プロジェクトの役にも立つ
- OpenStreetMapは、プロジェクト間のデータ共有プラットフォームが本質
- WebサーバーはGitHubをお借りする(Pages利用)ので無料
- OpenStreetMapのデータはOverPass APIを利用するので登録不要&無料
- 後はHTMLとJavaScriptでコードを書くだけでテイクアウトマップが作れる
OverPass APIについて
- 大雑把に書くと、JavaScriptからOpenStreetMapの「データ」を取得するAPIのこと
- 「データ」とは緯度経度付きの地物(施設、建物、道路、川、森、石碑など)
- ビジネスなど大量アクセスしない限り、登録不要・無料で使えるAPIサーバーがある
- クエリをAPIを呼ぶことで、欲しいデータだけを抜き出せる(例えば酒屋だけ抜き出す)
- 簡単な使い方は、OpenStreetMap Advent Calendar 2019「OverPass APIのススメ」参照
Overpass APIでテイクアウト店舗を取得する
-
GitHub: みんなでテイクアウトMAP <開発版>
-
動作画面 / デモサイト
-
動作画面のポイント
- 画面左側
- 背景地図は何でも良い。例えばGoogle Maps(開発が必要だけど)でもOK
- もちろん、OpenStreetMap標準タイルサーバーを利用してもOK
- 今回は日本でもサービスが始まった Maptiler を利用してみた
- OverPass APIで取得した店舗に合ったアイコンを表示させている
- 背景地図は画像だけ利用し、APIで取得したデータを上に表示させている
- 背景地図は何でも良い。例えばGoogle Maps(開発が必要だけど)でもOK
- 画面右側
- OverPass APIで取得した店舗をリスト(ソート順は中心位置からの近さ)
- GeoJsonで取得できるので、サーバーを別に用意する必要は無い
- 画面左側
ソースコードの説明
OverPass APIの利用
- OvPassCntクロージャのgetでデータを取得している
- getの引数(targets)の内容は ["takeaway","delivery"] といった単なる配列
- コード後半の targets.forEach でループさせて Conf.target[key].ovpass でOverPass APIに投げるクエリを取得させている
takeawayLib.js
var OvPassCnt = (function () {
var Cache = { "geojson": [], "targets": [] }; // Cache variable
var LLc = { "NW": { "lat": 0, "lng": 0 }, "SE": { "lat": 0, "lng": 0 } }; // latlng cache area
return {
get: function (targets) {
return new Promise((resolve, reject) => {
// 中略 //
targets.forEach(key => {
for (let ovpass in Conf.target[key].ovpass) { query += Conf.target[key].ovpass[ovpass] + maparea };
});
let url = OvServer + '?data=[out:json][timeout:30];(' + query + ');(._;>;);out meta qt;';
console.log("GET: " + url);
jqXHRs.push($.get(url, () => { DisplayStatus.progress(100) }));
- 最終的にOverPass APIには以下のような内容で投げている(サンプルはシンプルにしてます)
- 実際にクエリを投げてみるとJsonで返ってくることが分かる
GET: https://overpass-api.de/api/interpreter?data=[out:json][timeout:30];(node["takeaway"](34.689042740830814,135.44517159461978,34.715592149311874,135.48583388328555););(._;>;);out meta qt;
APIの返答結果をマーカー表示
- OverPass APIから取得したデータを変数に格納して、それをマーカー表示させる部分
- マーカー表示には leaflet.js のDivIconを利用している(背景地図もleaflet.js)
takeawayLib.js
var Marker = (function () {
var markers = [];
return {
set: function (target) {
markers[target] = [];
let pois = PoiCont.get_target(target);
pois.geojson.forEach(function (node, idx) {
let tags = node.properties;
let name = tags.name == undefined || Conf.local.TextViewZoom > map.getZoom() ? "" : tags.name;
let keyn = tags.amenity !== undefined ? "amenity" : "shop";
let icon = Conf.icon[keyn][tags[keyn]];
icon = "./image/" + (icon !== undefined ? icon : Conf.icon.default);
let html = '<div class="d-flex align-items-center"><img class="icon" src="' + icon + '"><span class="icon">' + name + '</span></div>'
icon = L.divIcon({ "className": 'icon', "iconAnchor": [8, 8], "html": html });
markers[target].push(L.marker(new L.LatLng(pois.latlng[idx].lat, pois.latlng[idx].lng), { icon: icon, draggable: false }));
markers[target][markers[target].length - 1].addTo(map).on('click', e => Takeaway.view(e.target.takeaway_id));
});
},
詳しくはソースで!
- 紹介した「みんなでテイクアウトMAP」はオープンソース(MITライセンス)で公開中
- OverPass APIに渡すクエリと周辺を書き換えると、例えば「トイレマップ」なんかも作れる
- GitHub: みんなでテイクアウトMAP <開発版>
- (参考) OpenStreetMap Wiki: JA:Overpass API
もし良ければ、「みんなでテイクアウトMAP」を開発した理由も読んで頂けるとありがたいです。