4
17
2016
Leafletを試してみた
Leafletは結構使い易そう
国土地理院が公開しているWebマップサービス 『地理院地図』がこの3月に更新されて機能アップがはかられたが、現在の『地理院地図』は Leaflet というJavascriptベースのフレームワークを用いて開発されている.
国土地理院のWebマップシステムも、独自のJavascriptコードから、電子国土V4でOpenLayersへと切り替わったが、このままOpenLayers路線で行くのかと思いきや、ここ1年ちょっとの間はLeafletに置き換えられてしまった.地図タイルの仕様も変化してしまっているので、開発側としてはその度にシステムの修正を加えなければならなかったので、できれば今回のLeafletで当面落ち着いて欲しいところだ.
一般的なJavascriptベースのWebマップフレームワークとして最もポピュラーなものは Google Maps ということになるが、Googleという一企業のものなので今後も使い続けられるとは限らない.個人ベースではライセンス費用は掛からないが、所謂Google税を払ってまで使いたいとは思わない.
Google Mapsに代わるオープンソースベースのWebマップフレームワークとして、これまでは OpenLayersが注目されていたが、フレームワークの使い方に結構癖があり、ドキュメントも揃っておらずOpenLayersを使いこなすのは結構骨が折れる.
OpenLayersに代わるものとして、Leafletというものが有ることは知っていたが、『地理院地図』がこのLeafletを使ってかなり高機能な実装が行われているので、試しに簡単なサンプルコードを書いてみた.
Leafletを使って見た感想としては、結構簡単に使いこなせそうだと感じた.Google Mapsでの開発に慣れた人で在れば、ほぼ同じような感覚で使いこなすことができそうだ.このサンプルも Leaflet のドキュメントを参考に、僅かな時間で書くことができた.今後は私もLeafletをベースとしてWebマップシステムを開発して行こうと思う.
地図データ: 地理院地図(国土地理院)
サンプルコード
https://y2tech.net/maps/GSILeafletSamples/GSILeafletSample01.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>GSI Tiles on Leaflet</title>
<link rel="stylesheet" href="https://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css" />
<script src="https://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
<style>
body { padding: 0; margin: 0 }
html, body,
#leaflet_map { height: 640px; width: 100%; },
</style>
</head>
<body>
<div id="leaflet_map"></div>
<script>
var mapAttr = '<a href="http://maps.gsi.go.jp/development/ichiran.html" target="_blank">地理院タイル</a>';
var GSIStandardTile = L.tileLayer( 'https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png', { attribution: mapAttr } );
var GSIPaleTile = L.tileLayer( 'https://cyberjapandata.gsi.go.jp/xyz/pale/{z}/{x}/{y}.png', { attribution: mapAttr } );
var GSIOrthoTile = L.tileLayer( 'https://cyberjapandata.gsi.go.jp/xyz/ort/{z}/{x}/{y}.jpg', { attribution: mapAttr } );
var photoMarkers = new L.LayerGroup();
var cameraIcon = L.icon({
iconUrl: './icons/dcam.png',
iconSize: [24, 24],
iconAnchor: [12, 12],
popupAnchor: [-3, -16]
});
var gotenbaPopup = L.popup( { minWidth: 260 } ).setContent('<p> <img src="./photo/gotenba.jpg" /><br /> 御殿場口 (新5合目)</p>');
var subashiriPopup = L.popup( { minWidth: 260 } ).setContent('<p> <img src="./photo/subashiri.jpg" /> <br /> 須走口 (5合目)</p>');
var fujinomiyaPopup = L.popup( { minWidth: 260 } ).setContent('<p> <img src="./photo/fujinomiya.jpg" /><br /> 富士宮口(5合目) </p>');
var suyamaPopup = L.popup( { minWidth: 260 } ).setContent('<p> <img src="./photo/suyama.jpg" /> <br /> 須山口(1合目) </p>');
L.marker( [35.335713, 138.794575], { icon: cameraIcon } ).bindPopup( gotenbaPopup ).addTo( photoMarkers ),
L.marker( [35.366481, 138.778439], { icon: cameraIcon } ).bindPopup( subashiriPopup ).addTo( photoMarkers ),
L.marker( [35.337009, 138.734193], { icon: cameraIcon } ).bindPopup( fujinomiyaPopup ).addTo( photoMarkers ),
L.marker( [35.306300, 138.770714], { icon: cameraIcon } ).bindPopup( suyamaPopup ).addTo( photoMarkers );
var kengamine = L.latLng( 35.360496, 138.727541 );
var map = L.map( 'leaflet_map', {
center: kengamine,
zoom: 12,
scrollWheelZoom: false,
layers: [ GSIStandardTile, photoMarkers ]
} );
var baseLayers = {
"標準地図": GSIStandardTile,
"淡色地図": GSIPaleTile,
"写真(オルソ)": GSIOrthoTile
};
var overlays = {
"登山口": photoMarkers
};
L.control.layers( baseLayers, overlays ).addTo( map );
function onMapRightClick( e ) {
L.popup( { minWidth: 260 } ).setContent('<p>位置情報:' + e.latlng + '<br></p>').setLatLng( e.latlng ).openOn( map );
}
map.on( 'contextmenu', onMapRightClick );
map.setView( [35.353496, 138.741961], 12 );
</script>
</body>
</html>