シンプルなサンプルプログラムで解説
「まち歩きマップメーカー」のソースを解説しようとしたけど複雑なので諦めました。代わりに、サンプルプログラムを作ったので、それの解説を行います。
対象者
- JavaScriptでフロントエンド開発をされている方
- WikipediaをWebアプリで利用したいと考えている方
- OpenStreetMapのデータを取得したいと考えている方
- QRコード生成のサンプルプログラムが欲しい方
利用するライブラリ
- QRコード生成
- OpenStreetMapデータをgeoJsonへ変換
- 地図を表示
- jQuery(単にajaxでgetしてるだけです)
ソースコードとデモ
- ソースコード
- デモ
ソース解説
<html>
<head>
<link rel="shortcut icon" href="favicon.ico" />
<link rel="stylesheet" href="base.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet@1.6.0/dist/leaflet.css" />
<script defer src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script defer src="https://cdn.jsdelivr.net/npm/leaflet@1.6.0/dist/leaflet-src.js"></script>
<script defer src="https://cdn.jsdelivr.net/npm/qrcode-svg@1.1.0/lib/qrcode.min.js"></script>
<script defer src="./osmtogeojson.js"></script>
<script defer src="./makeqr.js"></script>
</head>
<body>
<div id="mapid"></div>
</body>
</html>
シンプルにcssとライブラリの読み込みのみ。makeqr.jsはプログラム本体です。
leafletで地図を表示するため、"mapid"のidを付与したdivを配置しています。
"use strict";
var LL = {}; // 緯度(latitude)と経度(longitude)
const OvServer = 'https://overpass-api.de/api/interpreter'
const api_query = 'way["name"="大阪城"]';
const api_wikipedia = "wikipedia.org/w/api.php?format=json&action=query&prop=extracts&exintro=&explaintext=&titles=";
// initialize leaflet
let map = L.map('mapid', { center: [34.6867, 135.5273], zoom: 16 });
let osm_std = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { maxNativeZoom: 19, attribution: '© <a href="https://osm.org/copyright">OpenStreetMap</a> contributors' }).addTo(map);
// get OpenStreetMap data & get Wikipedia text & write QR Code
osmdata_get(api_query).then(geojson => {
let coords = geojson.features[0].geometry.coordinates[0][0];
let wiki = geojson.features[0].properties.wikipedia.split(':');
let url = encodeURI(`https://${wiki[0]}.wikipedia.org/wiki/${wiki[1]}`);
let latlng = { lat: coords[1], lng: coords[0] };
wikipedia_get(wiki[0], wiki[1]).then(text => qr_add(url, latlng, text)); // make QR Code
});
最初にconstで利用するサーバーと検索用クエリを定義しています。
api_queryはOverPass APIに投げるクエリ(詳細はOverPass APIのススメ)。
const後は、背景地図を表示させるleafletの初期化処理を行っています。
※緯度経度をパラメータに指定しています。場所は大阪城の天守閣周辺です。
その後、関数osmdata_getを呼んで、OpenStreetMapから大阪城を取得します。
取得後、変数coordsで緯度経度を取得し、変数wikiに["ja","大阪城"]が入ります。
※OpenStreetMapのwikipediaタグは「言語:記事名」の文字列となっているため。
変数wikiの設定後、変数urlにwikipediaへのリンクURLを設定(エンコード含む)。
変数latlngは、変数coordsをオブジェクト化(単に値の入れ直し)しています。
変数の設定後、関数wikipedia_getを呼び、その返り値を関数qr_addへ引き渡して、
QRコードを生成させています。最後に地図上に表示させて完了となります。
// get OpenStreetMap data
function osmdata_get(ovpass) {
return new Promise((resolve) => {
LL.NW = map.getBounds().getNorthWest();
LL.SE = map.getBounds().getSouthEast();
let maparea = '(' + LL.SE.lat + ',' + LL.NW.lng + ',' + LL.NW.lat + ',' + LL.SE.lng + ');';
let query = OvServer + '?data=[out:json][timeout:30];(' + ovpass + maparea + ');out body;>;out skel qt;'
$.get(query).done(function (data) {
let geojson = osmtogeojson(data, { flatProperties: true });
resolve(geojson);
});
});
};
// get Wikipedia text
function wikipedia_get(lang, name) { // get wikipedia contents
return new Promise((resolve) => {
let encurl = "https://" + lang + "." + api_wikipedia + encodeURI(name);
$.get({ url: encurl, dataType: "jsonp" }, function (data) {
let key = Object.keys(data.query.pages);
let text = data.query.pages[key].extract;
resolve(text);
});
});
}
function qr_add(url, latlng, text) {
let qrcode = new QRCode({ content: url, join: true, container: "svg", width: 128, height: 128 });
let data = qrcode.svg();
let icon = L.divIcon({ "className": "icon", "iconSize": [512, 128], "html": `<div style="float: left;">${data}</div><div>${text}</div>` });
let qr_marker = L.marker(new L.LatLng(latlng.lat, latlng.lng), { icon: icon, draggable: true });
qr_marker.addTo(map);
};
サンプルで用意した自作関数は3つのみ。上から説明していきますね。
osmdata_get(ovpass)
- ovpassは、OpenStreetMapのデータを取得するOverPass APIのクエリ文です。
- サンプルでは「way["name"="大阪城"]」の文字列が入っています。
- 緯度経度などをURLにセットして、APIサーバーからgetする内容です。
- 処理の成功後、osmtogeojsonでgeoJsonへ変換して値を返します。
wikipedia_get(lang, name)
- langは、Wikipediaの言語(日本語版はja)。サンプルでは「ja」が入ります。
- nameは、Wikipediaの記事名。サンプルでは「大阪城」が入ります。
- 記事名をエンコードしてからwikipediaのAPIを呼び出しています。
- 変数api_wikipediaは最初のconstに書いてあり、概要取得のパラメータです。
- get後、少し面倒なオブジェクトが返ってくるので対処しています。
qr_add(url, latlng, text)
- urlは、QRコードが指し示すURLを指定します。
- latlngは、OpenStreetMapから取得した大阪城の移動経度が入ります。
- textは、Wikipediaから取得した記事の概要テキストが入ります。
- 変数qrcodeは、urlをQRコードに変換した後のオブジェクトが入ります。
- 変数dataは、qrcodeから<svg>タグのテキストを生成しています。
- 変数iconは、QRコードと概要をアイコン化したオブジェクトが入ります。
- その後、変数iconをleafletのアイコンとして表示させています。
如何でしたでしょうか?
思ったより簡単に、OpenStreetMapとWikipediaからデータを取得できました。
データが取得出来たら、QRコードにしてリンクしても、表示させても良しです。
アイデア次第で様々なことに活用できると思います。しかも全世界対応ですよ!
なお、以下のライセンスに関する説明を読んでからデータを利用してください。
おまけ
-
フロントエンド開発で好きなマップを作る
- もう少し複雑な地図アプリを開発してみたい方向けの解説です。
-
まち歩きマップメーカー
- 今回のQRコード生成機能を実際に実装しているWebアプリです。