Leaflet とは
Leafletは、地図データを扱うためのJavaScript ライブラリ。Google Maps PlatoformやYOLPのようなメソッドで、地図情報の操作ができる。
Leaflet のウェブサイト
https://leafletjs.com/
Leafletのレポジトリ
https://github.com/Leaflet/Leaflet
Vladimir Agafonkinというエンジニアによって開発された。
著作権は、Vladimir および各コントリビュータに帰属しているが、BSDライセンスを採用しているため、著作権の表示と免責条項さえ明記しておけば、再利用も再配布も自由となる。
Leafletを使えば、すぐに地図が使えるか
No、Leaflet自体は単なるJSライブラリで、地図データを持っていない。
Leaflet で地図を表示するためにはどうすれば良いか
Leallet とは別に、地図サービスからデータを取得する必要がある。
例えば MapBox という有名な地図情報サービスと組み合わせ使うことができる。
この場合、MapBoxにアカウントを作成し、APIキーをあらかじめ取得する必要がある。
利用頻度に応じて、MapBoxに利用料を払う必要がある。
面白い例として、Leaflet にGoogle Maps のデータを組み合わせて表示することも可能なようだ(ただしライセンス違反になる可能性が高い)。
この場合、地図の画像データはGoogle Mapsを使い、描画するためのライブラリにLeafletを利用する形となる。
いずれにせよ、利用する地図データの規約に合わせて、APIキーを取得したり、費用を払う必要がある。
OpenStreetMap とは
OpenStreatMap財団が「Open Data Commons Open Database License (ODbL)」 の下にライセンスするオープンデータ。OpenStreetMapとその協力者をクレジットすれば、データを自由にコピー、配布、送信、利用することができる。料金はかからない。
ライセンスはCreative Commons.
https://www.openstreetmap.org/copyright/ja
Leaflet+ OpenStreetMap 基本的な使い方
公式サイトのチュートリアルが詳しい。
Laefletのライブラリ(CSS、JS)を読み込み、地図データをOpenStreetMapから呼び出して使う。
Leafletを使う場合、必ずCSSを先に呼び出し、その後にJSライブラリを読み込む必要がある。
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css"
integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=="
crossorigin=""/>
<!-- Make sure you put this AFTER Leaflet's CSS -->
<script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js"
integrity="sha512-gZwIG9x3wUXg2hdXF6+rVkLF/0Vi9U8D2Ntg4Ga5I5BZpVkVxlJWbSQtXPSiUTtC0TjtGOmxa1AJPuV0CPthew=="
crossorigin=""></script>
ライブラリ読み込み後、htmlの body内に、地図表示のためのDOMを設定する。
<div id="mapid"></div>
地図表示用のDOMサイズを、個別にCSSで指定する。
#mapid { height: 500px; }
DOMの準備ができたら、地図オブジェクトを生成してOpenStreetMapの画像タイルを読み込む。
var map = L.map('mapid', {
center: [35.66572, 139.73100],
zoom: 17,
});
var tileLayer = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>',
});
tileLayer.addTo(map);
サンプルコード
地図上にマーカーを表示する
DOMに地図を描画した後、マーカーの情報をオブジェクトに追加する。
// 六本木を中心に地図描画
var map = L.map('mapid', {
center: [35.66572, 139.73100],
zoom: 17,
});
// OpenStreetMap から地図画像を読み込む
var tileLayer = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>',
});
tileLayer.addTo(map);
// マーカー画像の場所を指定する
L.marker([35.66572, 139.73100]).addTo(map);
動作サンプル
複数のマーカーを表示する
// 六本木を中心に地図描画
var map = L.map('mapid', {
center: [35.66572, 139.73100],
zoom: 17,
});
// OpenStreetMap から地図画像を読み込む
var tileLayer = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>',
});
tileLayer.addTo(map);
// マーカー画像の場所を指定する
L.marker([35.66572, 139.73100]).addTo(map); //1つ目のマーカー
L.marker([35.6662186, 139.7303961]).addTo(map); //2つ目のマーカー
動作サンプル
Leaflet+OSM Sample02 マーカーを複数表示
geoJson を利用して複数のマーカーを表示する
geoJson は、地理情報を扱うためのJSONフォーマット。
Leafletに用意されている 「geoJson」 メソッドを利用する
// 六本木を中心に地図描画
var map = L.map('mapid', {
center: [35.66572, 139.73100],
zoom: 17,
});
// OpenStreetMap から地図画像を読み込む
var tileLayer = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>',
});
tileLayer.addTo(map);
var features = [];
var place = [{
"name": "東京ミッドタウン",
"lat": "35.66572",
"long": "139.73100"
}, {
"name": "サントリー美術館",
"lat": "35.6662186",
"long": "139.7303961"
}, ]
// GeoJSON形式で複数個のマーカーを設定する
for (var i = 0; i < place.length; i++) {
features.push({ // 1つのマーカーの情報を格納する
"type": "Feature",
"properties": {
"name": place[i].name
},
"geometry": {
"type": "Point",
"coordinates": [place[i].long, place[i].lat]
}
});
}
L.geoJson(features).addTo(map);
注意点
geoJson でマーカーを表示する際は、「経度」→「緯度」で位置情報を指定する必要がある。
"coordinates": [place[i].long, place[i].lat]
「緯度」→「経度」で指定すると、期待通りの描画にならないため、要注意。
動作サンプル
Leaflet+OSM Sample03 geoJson でマーカーを複数表示
マーカーをクリックするとポップアップを表示する
「bindPopup」でイベントをバインドする
var map = L.map('mapid', {
center: [35.66572, 139.73100],
zoom: 17,
});
var tileLayer = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>',
});
tileLayer.addTo(map);
var features = [];
var place = [{
"name": "東京ミッドタウン",
"lat": "35.66572",
"long": "139.73100"
}, {
"name": "サントリー美術館",
"lat": "35.6662186",
"long": "139.7303961"
}, ]
// GeoJSON形式で複数個のマーカーを設定する
for (var i = 0; i < place.length; i++) {
features.push({
"type": "Feature",
"properties": {
"name": place[i].name
},
"geometry": {
"type": "Point",
"coordinates": [place[i].long, place[i].lat]
}
});
}
L.geoJson(features, {
onEachFeature: function(features, layer) {
if (features.properties && features.properties.name) {
layer.bindPopup(features.properties.name);
}
}
}).addTo(map);
動作サンプル
Leaflet+OSM Sample04 マーカーをクリックするとポップアップが表示される
マーカーに MouseOver、Click イベントを仕掛ける
先にbindPopup をバインドし、MouseOver, click イベントを重ねる。
- マーカーの上にマウスを重ねると、ポップアップが表示
- マーカーをクリックすると、アラートが表示される
というユースケースで書いてみた。
var map = L.map('mapid', {
center: [35.66572, 139.73100],
zoom: 17,
});
var tileLayer = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>',
});
tileLayer.addTo(map);
var features = [];
var place = [{
"name": "東京ミッドタウン",
"lat": "35.66572",
"long": "139.73100"
}, {
"name": "サントリー美術館",
"lat": "35.6662186",
"long": "139.7303961"
}, ]
// GeoJSON形式で複数個のマーカーを設定する
for (var i = 0; i < place.length; i++) {
features.push({
"type": "Feature",
"properties": {
"name": place[i].name
},
"geometry": {
"type": "Point",
"coordinates": [place[i].long, place[i].lat]
}
});
}
L.geoJson(features, {
onEachFeature: function(features, layer) {
if (features.properties && features.properties.name) {
layer.bindPopup(features.properties.name);
layer.on('mouseover', function(e) {
this.openPopup();
});
layer.on('mouseout', function(e) {
this.closePopup();
});
layer.on('click', function(e) {
alert('Yay!');
});
}
}
}).addTo(map);
動作サンプル
Leaflet+OSM Sample05 マーカーにonMouse、onClickそれぞれにイベントを仕掛ける
地図の中央に十字マークを表示する
「あちあち情報局」様のコードを参考にしました。
十字マークは、国土地理院より拝借。
// 十字マークを地図中央に表示
var crossIcon = L.icon({
iconUrl: 'https://maps.gsi.go.jp/image/map/crosshairs.png',
iconSize: [32, 32],
iconAnchor: [16, 16]
});
var crossMarker = L.marker( map.getCenter(),{
icon:crossIcon,
zIndexOffset:1000,
interactive:false
}).addTo(map);
map.on('move', function(e) {
crossMarker.setLatLng(map.getCenter());
});
動作サンプル
Leaflet+OSM Sample06 地図の中央に十字マークを表示する
現在地の情報を取得して地図を表示する
「locate」 メソッドを使う。geoLocation のラッパーのようで、ブラウザが geoLocation API 対応なら、現在地を取得して処理を行ってくれる。
locateメソッドとは別に、onLocationFound, onLocationError という2つのメソッドがある。
それぞれ、現在位置の取得の成功・失敗に応じてイベントの発火ができる。
より細かい処理が必要な場合に有用。
// 現在地を取得して、地図を描画する
function getgeo() {
map.on('locationerror', onLocationError);
map.locate({
setView: "true"
});
}
function onLocationError(e) {
alert(e.message);
}
動作サンプル
Leaflet+OSM Sample07 現在地の地図を表示する
地図の縮尺について
PCの画面で locateメソッドを使うと、地図の描写がZoomOutされ、細かい地図の描写ができない。
その一方、スマートフォンで locate 機能を使うと、直前まで表示していた地図の縮尺レベルを保ったまま、現在地周辺の地図を描画する。
スマホで使う分には問題ないが、ちょっと気持ち悪い。どうすれば解決するか、調査中。
地図をドラッグ移動後、中心点の緯度経度を表示する
「moveend」 メソッドを使う。getCenter と組み合わせて、
- 地図の移動終了を、moveend で検知し、イベント発火
- getCenter で中心地の緯度経度を取得する
という流れで処理する。
- 緯度は getCenter().lat
- 経度は getCenter().lng
で取得できる。
map.on('moveend', function(e) {
console.log("緯度: " + map.getCenter().lat);
console.log("経度: " + map.getCenter().lng);
});
動作サンプル
Leaflet+OSM Sample08 地図をドラッグ移動後、中心の緯度経度を表示
コントローラーの表示位置を調整する
を使うと楽。
LeafletにはDOM操作用のメソッドがいくつか用意されており、それを使う。
「右上」「右下」「左上」「左下」 の指定ができる。
map.zoomControl.setPosition("bottomleft");
StackOverflow をみていると、別なやり方も見つけられるが、上記の方がシンプル。
動作サンプル
Leaflet+OSM Sample09 Zoomコントローラーの位置を変える
実稼働例
個人で開発・運営しているウェブサービスに、Leaflet と OpenStreetMap で地図表示を行いました。こちらに反映してます。
- [天気の子 聖地ナビ] (https://www.tenkinokoseichi.link/)