LoginSignup
3
3

More than 3 years have passed since last update.

フロントエンド開発で好きなマップを作る

Last updated at Posted at 2020-12-14

「みんなでテイクアウト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でテイクアウト店舗を取得する

  • システム構成図
    image.png

  • GitHub: みんなでテイクアウトMAP <開発版>

  • 動作画面 / デモサイト
    image.png

  • 動作画面のポイント

    • 画面左側
      • 背景地図は何でも良い。例えばGoogle Maps(開発が必要だけど)でもOK
        • もちろん、OpenStreetMap標準タイルサーバーを利用してもOK
        • 今回は日本でもサービスが始まった Maptiler を利用してみた
      • OverPass APIで取得した店舗に合ったアイコンを表示させている
      • 背景地図は画像だけ利用し、APIで取得したデータを上に表示させている
    • 画面右側
      • 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」を開発した理由も読んで頂けるとありがたいです。

3
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3