7
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ベクトルタイルAdvent Calendar 2017

Day 15

Leaflet1.0系でGeoJSONタイルを扱うTIPS

Last updated at Posted at 2017-12-14

これは ベクトルタイル Advent Calendar 2017 の記事です。

はじめに

Leaflet で GeoJSON タイルを扱う方法としては L.TileLayer.GeoJSON プラグイン が定番で、国土地理院ベクトルタイル提供実験 でもこのプラグインを使ったデモを紹介しています。
ただ、このプラグインは一世代前の Leaflet0.7系を対象としていて、現行版である Leaflet1.0系では動作しません。作者も忙しいといっている ので今後も対応の見込みは薄そうです。

このエントリではプラグインや自前クラスを使わずにささっと Leaflet1.0系で GeoJSON タイルを表示する TIPS を紹介します。

デモ

image.png

https://bl.ocks.org/frogcat/raw/334998cbd13c4875211debf0a9e6f785/#17/35.66171/139.67930

ソース

index.html
<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0" />
  <title>Leaflet1.2 GeoJSON Tile Tips</title>
  <link rel="stylesheet" href="https://unpkg.com/leaflet@1.2.0/dist/leaflet.css" />
  <script src="https://unpkg.com/leaflet@1.2.0/dist/leaflet.js"></script>
  <script src="https://unpkg.com/leaflet-hash@0.2.1/leaflet-hash.js"></script>
</head>

<body>
  <div id="map" style="position:absolute;top:0;left:0;bottom:0;right:0;"></div>
  <script>
    // Initalize map
    var map = L.map("map", L.extend({
      minZoom: 17,
      zoom: 18,
      maxZoom: 22,
      center: [35.64430, 139.67124]
    }, L.Hash.parseHash(location.hash)));
    map.zoomControl.setPosition("bottomright");
    L.hash(map);

    // Add background layer
    L.tileLayer("https://cyberjapandata.gsi.go.jp/xyz/seamlessphoto/{z}/{x}/{y}.jpg", {
      attribution: "<a href='http://maps.gsi.go.jp/development/ichiran.html'>GSI</a>",
      maxZoom: 22,
      maxNativeZoom: 18
    }).addTo(map);

    // Create tilelayer with empty image
    L.tileLayer(L.Util.emptyImageUrl, {
      attribution: "<a href='http://maps.gsi.go.jp/development/ichiran.html'>GSI</a>",
      maxZoom: 22,
      maxNativeZoom: 18,
      minNativeZoom: 18
    }).on("tileload", function(event) {
      // Add tileload event handler to load geojson and add geojson layer
      var url = "https://cyberjapandata.gsi.go.jp/xyz/experimental_fgd/{z}/{x}/{y}.geojson";
      fetch(L.Util.template(url, event.coords)).then(a => a.ok ? a.json() : null).then(geojson => {
        if (!geojson || !this._map) return;
        event.tile.geojson = L.geoJSON(geojson, {
          style: function(geojson) {
            return {
              weight: 1.5,
              color: "#ffffff"
            };
          }
        }).addTo(this._map);
      });
    }).on("tileunload", function(event) {
      // Add tileunload event handler to remove geojson layer
      if (event.tile.geojson && this._map)
        this._map.removeLayer(event.tile.geojson);
    }).addTo(map);
  </script>
</body>

</html>

https://gist.github.com/frogcat/334998cbd13c4875211debf0a9e6f785

メモ

こんな仕組みです。

  1. 透明な画像を表示する L.TileLayer を作成
  2. L.TileLayer のタイル追加イベントを拾って GeoJSON の取得/L.GeoJSON の追加
  3. L.TileLayer のタイルの削除イベントを拾って L.GeoJSON の削除
L.tileLayer(L.Util.emptyImageUrl,{
  // レイヤーが表示される最大ズームレベル。デフォルトが18なので大きくしておく
  maxZoom: 22, 

  // ベクトルタイルの提供ズームレベル上限を指定
  maxNativeZoom: 18, 

  // ベクトルタイルの提供ズームレベル下限を指定
  minNativeZoom: 18 

}).on("tileload",function(event){

  // タイルをロードするときの処理を記述

}).on("tileunload",function(event){

  // タイルが消去されるときの処理を記述

}).addTo(map);
  • L.Util.emptyImageUrl はビルトインの透過GIFです
  • tileload event はタイルを読み込んだときに発行されるイベントです
  • 同様に tileunload event はタイルが不要になったときに発行されるイベントです
  • maxNativeZoom / minNativeZoom にはベクトルタイルの提供ズームレベルの上下限を指定します

Leaflet1.0は従来の maxNativeZoom に加えて minNativeZoom にも対応しているので、上のような設定で勝手にオーバーズーミングもやってくれます。ただ、minNativeZoom を設定した状態でズームアウトするととてもたくさんのタイルを取得しに行くことになるので注意しましょう。

7
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?