世界の測量

Sibling of "Relevant, Timely, and Accurate, " but much lighter and shorter ※自らの所属する組織の見解を示すものでない

MapReduce的ベクトルタイル作成(地価公示)Pt. 4

間があいてしまったが、前回作成したベクトルタイルデータを表示する。
http://handygeospatial.github.io/mapsites/2014/02/11/ の解説である。
f:id:hfu:20140211051912p:plain

ソースコード

index.html のソースコードは、次の通りである。その他、leaflet-hash.js と TileLayer.GeoJSON.js を同フォルダにアップロードしてある。

<!doctype html>
<html>
<head>
  <meta charset='UTF-8'>
  <meta name="viewport" 
   content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
  <meta name="apple-mobile-web-app-capable" content="yes"/>
  <meta name="apple-mobile-web-app-status-bar-style" 
   content="black-translucent" />
  <title>国土数値情報(地価公示)</title>
  <link rel='stylesheet' href='http://leafletjs.com/dist/leaflet.css'>
  <script src='http://leafletjs.com/dist/leaflet.js'></script>
  <script src="leaflet-hash.js"></script>
  <script src="TileLayer.GeoJSON.js"></script>
  <style>
  html, body, #mapdiv {margin: 0; padding: 0; width: 100%; height: 100%;}
  </style>
</head>
<body>
  <div id='mapdiv'/>
  <script>
function _tr(prop, name) {
  if(prop[name] == '' || prop[name] == undefined) { 
    return '';
  } else {
    return "<tr><td>" + name + "</td><td>" + prop[name] + "</td></tr>";
  }
}

function render_properties(prop) {
  var s = ''
  for(i in prop) {
    s += _tr(prop, i);
  }
  return "<table border='1'>" + s + "</table>";
}

icon = L.icon({
  iconUrl: 'http://cyberjapan.jp/symbols/090.bmp', iconSize: [16, 16]});
map = new L.Map('mapdiv', {zoom: 16, center: [35.6762, 139.7653]});
hash = new L.Hash(map);
map.addLayer(new L.TileLayer(
  'http://cyberjapandata.gsi.go.jp/xyz/pale/{z}/{x}/{y}.png',
  {attribution: '地理院タイル'}));
map.addLayer(new L.TileLayer.GeoJSON(
  'http://www.handygeospatial.info/2014/01/22/{z}/{x}/{y}.geojson',
  {attribution: '国土数値情報(地価公示)', unloadInvisibleTiles: true,
   minZoom: 14, maxZoom: 18},
  {style: {"clickable": true},
   onEachFeature: function(feature, layer) {
     layer.bindPopup(render_properties(feature.properties));
     layer.setIcon(icon);
   }
  }));
  </script>
</body>
</html> 

部分ごとの解説

<!doctype html>
<html>
<head>
  <meta charset='UTF-8'>
  <meta name="viewport" 
   content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
  <meta name="apple-mobile-web-app-capable" content="yes"/>
  <meta name="apple-mobile-web-app-status-bar-style" 
   content="black-translucent" />
  <title>国土数値情報(地価公示)</title>

普通のHTMLの記述である。マルチタップデバイスでも動作することをめざして、その辺りのメタ情報を加えてある。

  <link rel='stylesheet' href='http://leafletjs.com/dist/leaflet.css'>
  <script src='http://leafletjs.com/dist/leaflet.js'></script>
  <script src="leaflet-hash.js"></script>
  <script src="TileLayer.GeoJSON.js"></script>

必要なウェブ地図ライブラリをロードしている。

  <style>
  html, body, #mapdiv {margin: 0; padding: 0; width: 100%; height: 100%;}
  </style>
</head>
<body>
  <div id='mapdiv'/>
  <script>

フルスクリーンのLeafletサイトを作成するときの定番のスタイルシート記述である。地図ディビジョンに全画面を割り当てている。

function render_properties(prop) {
  var s = ''
  for(name in prop) {
    s += "<tr><td>" + name + "</td><td>" + prop[name] + "</td></tr>";
  }
  return "<table border='1'>" + s + "</table>";
}

属性吹き出しの中身を作成するための関数である。render_propertiesは、地物属性のオブジェクトをRubyのHashオブジェクト風に受け取り、それぞれのキーごとに、HTMLのtrを作成させ、tableに入れて返す。

icon = L.icon({
  iconUrl: 'http://cyberjapan.jp/symbols/090.bmp', iconSize: [16, 16]});

ポイントデータにあとで割り当てるアイコンを設定している。iconUrlはアイコンのURLである。iconSizeはアイコンのサイズである。アイコンのサイズを指定することで、アイコンの中央がデータ上の点になる。アイコンのサイズを指定しなかった場合、アイコン画像の左上がデータ上の点になったと思う。

map = new L.Map('mapdiv', {zoom: 16, center: [35.6762, 139.7653]});

初期位置を明示して、地図ディビジョンを作成している。URLにハッシュが含まれていない場合には、この初期位置が使われることになる。

hash = new L.Hash(map);

leaflet-hash を地図ディビジョンに設定している。URLにハッシュが含まれる場合には、初期位置がそこに変更されるし、地図がスクロールするごとにURL上のハッシュが変更されることになる。結果として、任意の地図表示の際にアドレスバーからURLをコピーすると、現在の地図表示がURLに埋め込まれることになる。

map.addLayer(new L.TileLayer(
  'http://cyberjapandata.gsi.go.jp/xyz/pale/{z}/{x}/{y}.png',
  {attribution: '地理院タイル'}));

地理院タイル「淡色地図」を地図ディビジョンに加えている。ごくふつうの画像タイルである。

map.addLayer(new L.TileLayer.GeoJSON(
  'http://www.handygeospatial.info/2014/01/22/{z}/{x}/{y}.geojson',
  {attribution: '国土数値情報(地価公示)', unloadInvisibleTiles: true,
   minZoom: 14, maxZoom: 18},
  {style: {"clickable": true},
   onEachFeature: function(feature, layer) {
     layer.bindPopup(render_properties(feature.properties));
     layer.setIcon(icon);
   }
  }));

先日来作成していた「国土数値情報(地価公示)」のベクトルタイルを地図ディビジョンに追加する。
L.TileLayer.GeoJSONのコンストラクタは3つの引数を取る。1つめは普通通りのURLテンプレートであり、2つめは比較的標準的なプロパティ(GeoJSONTileLayer options)であり、3つめがベクトルタイル特有のプロパティ(GeoJSON options)である。オリジナルの技術情報は https://github.com/glenrobertson/leaflet-tilelayer-geojson/ にある。
3つめのプロパティ(GeoJSON options)で style: {"clickable": true} とすることにより、該当するアイコンがクリック選択になる。クリック選択後のアクションなど、地物ごとの設定を行うのが、onEachFeature プロパティである。ここでは、bindPopup で、先ほどの関数 render_properties を用いてポップアップの内容を設定し、setIcon でアイコンを設定している。