Leafletの使い方
LeafletはWeb地図サービスで広く使われるオープンソースのJavaScriptライブラリです。
ここでは、Leafletで地図を表示する方法をコードとともにわかりやすく解説します。
Google Maps APIの無料での利用に制限が多くなってきたので、Leafletに乗り換えたいという人の参考になれば幸いです。
なお、ここではバージョン1.3.0を使用しています。すべての機能を解説しているわけではないので、オブジェクトのメソッド、オプション、イベントなどは1.3.4の リファレンスを参考にしてください。
(2018/8/31基本編Step1-10公開、9/3 Step11-14、9/13 Step15、2020/4/1 Step16公開)
Step 12.タイルレイヤの重ね合わせ
- タイルレイヤはオーバーレイにも設定できる
- その際、ベースレイヤが見えるよう、透過度を指定するとよい
- タイルレイヤにより最大ズームレベルが異なる場合は、maxNativeZoomを設定すると拡大して表示される
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Step12.タイルレイヤの重ね合わせ|Lefletの応用|埼玉大学谷謙二研究室</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.0/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet@1.3.0/dist/leaflet.js"></script>
<script>
function init() {
var map = L.map('mapcontainer', { zoomControl: false });
map.setView([35.40, 136], 10);
var gsiattr = "<a href='http://portal.cyberjapan.jp/help/termsofuse.html' target='_blank'>地理院タイル</a>";
var gsi = L.tileLayer('https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png', { attribution: gsiattr });
var gsipale = L.tileLayer('http://cyberjapandata.gsi.go.jp/xyz/pale/{z}/{x}/{y}.png', { attribution: gsiattr });
var osm = L.tileLayer('http://tile.openstreetmap.jp/{z}/{x}/{y}.png',
{ attribution: "<a href='http://osm.org/copyright' target='_blank'>OpenStreetMap</a> contributors" });
//オーバーレイ用のタイルレイヤ
//opacityで透過度を設定、maxNativeZoomを指定すると、それ以上のズームレベルのタイルデータは、指定のズームレベルのタイル画像を拡大して表示される
var gsirelief = L.tileLayer('http://cyberjapandata.gsi.go.jp/xyz/relief/{z}/{x}/{y}.png', { opacity: 0.7, maxNativeZoom: 15, attribution: gsiattr });
var gsirehillshademap = L.tileLayer('http://cyberjapandata.gsi.go.jp/xyz/hillshademap/{z}/{x}/{y}.png', { opacity: 0.5, maxNativeZoom: 16, attribution: gsiattr });
var baseMaps = {
"地理院地図": gsi,
"淡色地図": gsipale,
"オープンストリートマップ": osm
};
var overlayMaps = {
"色別標高図": gsirelief,
"陰影起伏図": gsirehillshademap
};
L.control.layers(baseMaps, overlayMaps).addTo(map);
gsi.addTo(map);
}
</script>
</head>
<body onload="init()">
<div id="mapcontainer" style="position:absolute;top:0;left:0;right:0;bottom:0;"></div>
</body>
</html>
Step 13.地図画面上へのDiv要素の追加と位置の表示
- Leafletの地図上に独自のDOM要素を追加することができる
- 追加する際にidを設定しておくとgetElementByIdで後から操作できる
- マウス位置は、mousemoveイベント時のMouseイベント、e.latlngプロパティで取得する
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Step13.地図画面上へのDiv要素の追加と位置の表示|Lefletの応用|埼玉大学谷謙二研究室</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.0/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet@1.3.0/dist/leaflet.js"></script>
<style>
/* 作成するdivのCSS */
.infostyle {
border: solid 1px;
background-color: azure;
border-radius: 10px;
opacity: 0.8;
padding: 5px;
font-size: 15px;
color: black;
}
</style>
<script>
function init() {
var map = L.map('mapcontainer', { zoomControl: false });
var mpoint = [35.40, 136];
map.setView(mpoint, 5);
L.tileLayer('https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png', {
attribution: "<a href='https://maps.gsi.go.jp/development/ichiran.html' target='_blank'>地理院タイル</a>"
}).addTo(map);
//mousemoveイベントを設定
map.on('mousemove', onMapMousemove)
//左上にdivコントロールを表示
var latloninfo = L.control({ position: "topleft" });
latloninfo.onAdd = function (map) {
//divを作成
this.ele = L.DomUtil.create('div', "infostyle");
//後で使うためにidを設定
this.ele.id = "latlondiv";
//最初は非表示
this.ele.style.visibility = "hidden";
//div上のとmousemoveイベントがmapに連鎖しないように設定
this.ele.onmousemove = function (e) { e.stopPropagation() };
return this.ele;
};
latloninfo.addTo(map);
}
function onMapMousemove(e) {
//地図上を移動した際にdiv中に緯度経度を表示
var box = document.getElementById("latlondiv");
var html = "緯度:" + e.latlng.lat.toFixed(6) + "<br>" +
"経度:" + e.latlng.lng.toFixed(6);
box.innerHTML = html;
box.style.visibility = "visible";
}
</script>
</head>
<body onload="init()">
<div id="mapcontainer" style="position:absolute;top:0;left:0;right:0;bottom:0;"></div>
</body>
</html>
Step 14.地図画面上へのselect要素の追加とベースレイヤの切り替え
- ベースレイヤの選択は、Step4でやったようにLeaflet所定のコントロールからできるが、独自に作成することもできる
- Step13と同様にセレクトボックスを地図上に配置し、選択してタイルレイヤをベースレイヤに設定するサンプルである
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Step14.地図画面上へのselect要素の追加とベースレイヤの切り替え|Lefletの応用|埼玉大学谷謙二研究室</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.0/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet@1.3.0/dist/leaflet.js"></script>
<script>
var map;
var baseMaps;
function init() {
map = L.map('mapcontainer', { zoomControl: false });
var mpoint = [35.40, 136];
map.setView(mpoint, 5);
var gsiattr = "<a href='http://portal.cyberjapan.jp/help/termsofuse.html' target='_blank'>地理院タイル</a>";
var gsi = L.tileLayer('https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png', { attribution: gsiattr });
var gsipale = L.tileLayer('http://cyberjapandata.gsi.go.jp/xyz/pale/{z}/{x}/{y}.png', { attribution: gsiattr });
var osm = L.tileLayer('http://tile.openstreetmap.jp/{z}/{x}/{y}.png',
{ attribution: "<a href='http://osm.org/copyright' target='_blank'>OpenStreetMap</a> contributors" });
baseMaps = {
"地理院地図": gsi,
"淡色地図": gsipale,
"オープンストリートマップ": osm
};
//左上にselectコントロールを表示
var selBox = L.control({ position: "topleft" });
selBox.onAdd = function (map) {
//selectを作成
this.ele = L.DomUtil.create('select');
//後で使うためにidを設定
this.ele.id = "selectBaseLayer";
return this.ele;
};
selBox.addTo(map);
//selectコントロールの中身を設定する
var sel = document.getElementById("selectBaseLayer");
sel.setAttribute("onchange", "baseLayerChage()");
for (var key in baseMaps) {
var opt = L.DomUtil.create('option', '', sel);
//valueと表示文字にbaseMapsのキーを設定する
opt.value = key;
opt.innerText = key;
}
//最初のベースタイル
baseLayerChage();
}
function baseLayerChage() {
//既存のベースレイヤをremoveする
for (var key in baseMaps) {
if (map.hasLayer(baseMaps[key]) == true) {
map.removeLayer(baseMaps[key]);
}
}
//選択されたベースレイヤをmapに設定する
var sel = document.getElementById("selectBaseLayer");
var selTile = sel.options[sel.selectedIndex].value;
baseMaps[selTile].addTo(map);
}
</script>
</head>
<body onload="init()">
<div id="mapcontainer" style="position:absolute;top:0;left:0;right:0;bottom:0;"></div>
</body>
</html>
Step 15.複数マーカーの表示
- Step5~6で行ったマーカーについて複数まとめて表示
- 配列に座標とポップアップする文字を設定し、Forループで回してマーカーに設定
- fitBoundsメソッドで、マーカーすべてが表示されるように地図領域を設定
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Step15.複数マーカーの表示|Lefletの応用|埼玉大学谷謙二研究室</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.0/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet@1.3.0/dist/leaflet.js"></script>
<script>
//マーカーに表示したい対象の緯度経度とポップアップする名称を設定
var markerList = [
{ pos: [35.8645472, 139.6048663], name: "セブンイレブン浦和埼玉大学店" },
{ pos: [35.8689857, 139.6086909], name: "セブンイレブンさいたま大久保店" },
{ pos: [35.871305, 139.6128431], name: "ファミリーマート浦和上大久保店" },
{ pos: [35.8665389, 139.6133905], name: "ミニストップさいたま上大久保店" },
{ pos: [35.8650306, 139.6070633], name: "ローソン埼玉大学店" }
];
function init() {
var map = L.map('mapcontainer');
L.tileLayer('https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png', {
attribution: "<a href='https://maps.gsi.go.jp/development/ichiran.html' target='_blank'>地理院タイル</a>"
}).addTo(map);
//マーカー全体が入るボックスを作る
var bound = L.latLngBounds(markerList[0].pos, markerList[0].pos);
//markerListの設定でマーカーを追加
for (var num in markerList) {
var mk = markerList[num];
var popup = L.popup().setContent(mk.name);
L.marker(mk.pos, { title: mk.name }).bindPopup(popup).addTo(map);
//マーカー全体が入るボックスを広げる
bound.extend(mk.pos);
}
//マーカー全体が入るように地図範囲を設定する
map.fitBounds(bound);
}
</script>
</head>
<body onload="init()">
<div id="mapcontainer" style="position:absolute;top:0;left:0;right:0;bottom:0;"></div>
</body>
</html>
Step 16.タイル座標をGridlayerで表示
- タイル座標(z,x,y)をGridlayerメソッドを使って表示
- Gridlayerで表示するHTML要素は、クラスを作っておく
- L.control.layersでクラスをベースマップレイヤまたはオーバーレイレイヤに追加する
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Step16.タイル座標をGridlayerで表示する|Lefletの応用|埼玉大学谷謙二研究室</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.0/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet@1.3.0/dist/leaflet.js"></script>
<script>
function init() {
var map = L.map('mapcontainer', { zoomControl: false });
map.setView([35.40, 136], 0);
map.setMaxZoom(20);
var gsiattr = "<a href='http://portal.cyberjapan.jp/help/termsofuse.html' target='_blank'>地理院タイル</a>";
var gsipale = L.tileLayer('http://cyberjapandata.gsi.go.jp/xyz/pale/{z}/{x}/{y}.png', { attribution: gsiattr });
var osm = L.tileLayer('http://tile.openstreetmap.jp/{z}/{x}/{y}.png',
{ attribution: "<a href='http://osm.org/copyright' target='_blank'>OpenStreetMap</a> contributors" });
var osmNoLabels = L.tileLayer('http://tiles.wmflabs.org/osm-no-labels/{z}/{x}/{y}.png',
{ attribution: "<a href='http://osm.org/copyright' target='_blank'>OpenStreetMap</a> contributors" });
var baseMaps = {
"地理院地図(淡色地図)": gsipale,
"オープンストリートマップ": osm,
"OSM no labels": osmNoLabels
};
//GridLayerClassを変数に設定し、オーバーレイのタイルレイヤに設定
var zxyLayer = new GridLayerClass();
L.control.layers(baseMaps, { "XYZ": zxyLayer }).addTo(map);
osm.addTo(map);
zxyLayer.addTo(map);
}
//zxyを表示するタイルレイヤのクラス
var GridLayerClass = L.GridLayer.extend({
createTile: function (coords) {
//div要素でタイルを作成
var tileDiv = L.DomUtil.create('div', '');
tileDiv.setAttribute("style", "border: solid 1px");
//タイル要素の中にzxyを表示するdiv要素を作成
var coordsDiv = L.DomUtil.create('div', '', tileDiv);
coordsDiv.setAttribute("style", "position:absolute;background-color:white;padding:5px;border: solid 1px;left:10px;top:10px;font-size:15px");
coordsDiv.innerHTML = "z / x / y = " + coords.z + " / " + coords.x + " / " + coords.y;
return tileDiv;
},
});
</script>
</head>
<body onload="init()">
<div id="mapcontainer" style="position:absolute;top:0;left:0;right:0;bottom:0;"></div>
</body>
</html>
|