Leafletと国土地理院のGSIタイルデータを使った地図アプリの作成

# はじめに

Webアプリケーションで地図データを扱うAPIの代表格はGoogleMapsAPIかと思いますが、いろいろな制約があったりするので、別の方法で地図を使う方法がないかと検索したらLeafletというJavaScriptライブラリと国土地理院のデータが使用できるようなので、試した結果をまとめます。

# Leaflet

非常に軽量なライブラリで、サクサク動く上に必要最低限の機能がそろっています。
http://leafletjs.com

# 国土地理院

GoogleMapsAPIと同じような使い方ができるデータが公開されています。
普通の地図から複数年の航空写真、災害時の写真など興味深いものがいっぱいあるので、これを使わないのはもったい無い。
http://maps.gsi.go.jp/development/ichiran.html

# クイックスタートを読んでみる

LeafletのWebサイトにクイックスタートがあるので見てみます。
http://leafletjs.com/examples/quick-start/

...英語でした（汗）

でも、ソースコードをまとめてみれば何かわかるかもしれないので、ソースコードっぽい部分をまとめてみます。

```html:
 <link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.1/dist/leaflet.css" />
 <script src="https://unpkg.com/leaflet@1.0.1/dist/leaflet.js"></script>
 <div id="mapid"></div>
#mapid { height: 180px; }
var mymap = L.map('mapid').setView([51.505, -0.09], 13);
L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}', {
    attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://mapbox.com">Mapbox</a>',
    maxZoom: 18,
    id: 'your.mapbox.project.id',
    accessToken: 'your.mapbox.public.access.token'
}).addTo(mmap);
var marker = L.marker([51.5, -0.09]).addTo(mmap);
var circle = L.circle([51.508, -0.11], {
    color: 'red',
    fillColor: '#f03',
    fillOpacity: 0.5,
    radius: 500
}).addTo(mmap);
var polygon = L.polygon([
    [51.509, -0.08],
    [51.503, -0.06],
    [51.51, -0.047]
]).addTo(mmap);
marker.bindPopup("<b>Hello world!</b><br>I am a popup.").openPopup();
circle.bindPopup("I am a circle.");
polygon.bindPopup("I am a polygon.");
var popup = L.popup()
    .setLatLng([51.5, -0.09])
    .setContent("I am a standalone popup.")
    .openOn(mmap);
function onMapClick(e) {
    alert("You clicked the map at " + e.latlng);
}
mymap.on('click', onMapClick);
var popup = L.popup();
function onMapClick(e) {
    popup
        .setLatLng(e.latlng)
        .setContent("You clicked the map at " + e.latlng.toString())
        .openOn(mymap);
}
mymap.on('click', onMapClick);
```

...うん、わからない。

地図画像の下に「See this example stand-alone.」とリンクが貼ってあるので、クリックしてみる。
http://leafletjs.com/examples/quick-start/example.html

表示されたページのソースコードを表示すると以下のようになっていた。

```html:example.html
<!DOCTYPE html>
<html>
<head>
	
	<title>Quick Start - Leaflet</title>

	<meta charset="utf-8" />
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	
	<link rel="shortcut icon" type="image/x-icon" href="docs/images/favicon.ico" />

	<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.1/dist/leaflet.css" />
	<script src="https://unpkg.com/leaflet@1.0.1/dist/leaflet.js"></script>

</head>
<body>

<div id="mapid" style="width: 600px; height: 400px;"></div>
<script>

	var mymap = L.map('mapid').setView([51.505, -0.09], 13);

	L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpandmbXliNDBjZWd2M2x6bDk3c2ZtOTkifQ._QA7i5Mpkd_m30IGElHziw', {
		maxZoom: 18,
		attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, ' +
			'<a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
			'Imagery © <a href="http://mapbox.com">Mapbox</a>',
		id: 'mapbox.streets'
	}).addTo(mymap);

	L.marker([51.5, -0.09]).addTo(mymap)
		.bindPopup("<b>Hello world!</b><br />I am a popup.").openPopup();

	L.circle([51.508, -0.11], 500, {
		color: 'red',
		fillColor: '#f03',
		fillOpacity: 0.5
	}).addTo(mymap).bindPopup("I am a circle.");

	L.polygon([
		[51.509, -0.08],
		[51.503, -0.06],
		[51.51, -0.047]
	]).addTo(mymap).bindPopup("I am a polygon.");


	var popup = L.popup();

	function onMapClick(e) {
		popup
			.setLatLng(e.latlng)
			.setContent("You clicked the map at " + e.latlng.toString())
			.openOn(mymap);
	}

	mymap.on('click', onMapClick);

</script>

</body>
</html>
```

とりあえず、このソースをコピーしてデスクトップにHTMLファイルとして保存すると...

![スクリーンショット 2016-11-16 19.53.18.png](https://qiita-image-store.s3.amazonaws.com/0/114240/b16c61d9-6184-23da-9c25-8524143ec6a3.png)

できた！

...でも、これでは当初のテーマである国土地理院のデータを使っていないため、まだまだこれから。

# 地図データを変えてみる

25行目付近のコードがちょっと気になる。

```js:
	L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpandmbXliNDBjZWd2M2x6bDk3c2ZtOTkifQ._QA7i5Mpkd_m30IGElHziw', {
		maxZoom: 18,
		attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, ' +
			'<a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
			'Imagery © <a href="http://mapbox.com">Mapbox</a>',
		id: 'mapbox.streets'
	}).addTo(mymap);
```

「https://〜」で始まる部分と同じような表記が国土地理院のGSIページにあるので、勝手に書き換えてみる(^-^)
maxZoomは地理院タイルの情報にズームレベルが書いてあるので、ちょっと関係あるかもしれない。

```js:
	L.tileLayer('http://cyberjapandata.gsi.go.jp/xyz/ort/{z}/{x}/{y}.jpg', {
		maxZoom: 18
	}).addTo(mymap);
```

書き換えたら再読込。

![スクリーンショット 2016-11-17 8.56.45.png](https://qiita-image-store.s3.amazonaws.com/0/114240/ca400cdb-568c-e137-af3f-0b3792d3e7ff.png)

...何も表示されない。

ズームレベルをどんどん下げてみると、何か表示された。

![スクリーンショット 2016-11-17 8.58.14.png](https://qiita-image-store.s3.amazonaws.com/0/114240/1d9845c7-07e2-d011-e22a-c1f87e62f177.png)

地図を移動させると日本が出てきた。

![スクリーンショット 2016-11-17 8.59.43.png](https://qiita-image-store.s3.amazonaws.com/0/114240/335fb45c-8bd8-8626-207e-35dd41280260.png)

きっと、中心座標が間違っているからに違いない。

# 中心座標を変えてみる

```html:
	var mymap = L.map('mapid').setView([51.505, -0.09], 13);
```

となっている部分を去年国宝になった松江城の座標(35.47507, 133.05075)に書き換えてみる。

```html:
	var mymap = L.map('mapid').setView([35.47507, 133.05075], 13);
```

![スクリーンショット 2016-11-17 9.07.02.png](https://qiita-image-store.s3.amazonaws.com/0/114240/8d6f2d88-2424-7375-67b8-fee8fb18d239.png)


...あれ、まだダメだ（汗）

地図の描画以降に書いてるものが邪魔しているかもしれない。

「L.marker〜mmap.on(〜)」までを「/* 〜 */」で囲って無効にしてもう一度再読込。

![スクリーンショット 2016-11-17 9.09.52.png](https://qiita-image-store.s3.amazonaws.com/0/114240/2eb6b86c-0e24-6e25-ec1b-d842b42081d0.png)

来た！

# 全ソースコード

できたとこまでに必要なソースコードだけにまとめるととてもシンプル(^-^)

```html:example.html
<!DOCTYPE html>
<html>
<head>
	
	<title>Quick Start - Leaflet</title>

	<meta charset="utf-8" />
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	
	<link rel="shortcut icon" type="image/x-icon" href="docs/images/favicon.ico" />

	<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.1/dist/leaflet.css" />
	<script src="https://unpkg.com/leaflet@1.0.1/dist/leaflet.js"></script>
	
</head>
<body>

<div id="mapid" style="width: 600px; height: 400px;"></div>
<script>

	var mymap = L.map('mapid').setView([35.47507, 133.05075], 13);

	L.tileLayer('http://cyberjapandata.gsi.go.jp/xyz/ort/{z}/{x}/{y}.jpg', {
		maxZoom: 18
	}).addTo(mymap);

</script>

</body>
</html>
```

よし、これから何しよう！！