dayjournal memo

Total 975 articles!!

Try #054 – LeafletでGeoPackageを読み込んで表示してみた

Yasunori Kirimoto's avatar

画像




画像




この記事は、「MIERUNE Advent Calendar 2020」の17日目の記事です。


LeafletでGeoPackageを読み込んで表示してみました!

QGISでよく利用するGeoPackageですが、実はLeafletで読み込んで表示することもできたりします。

LeafletでGeoPackageを読み込んで表示する場合は、GeoPackage JSを利用したleaflet-geopackageで実現できます。



利用データ

今回は、QGISQuickOSMプラグインでOpenStreetMapのshopデータを5000件程度準備してGeoPackageで保存しました。



Leaflet


次に、Leafletで構築していきます。 leaflet-geopackageは、webpackに対応していないみたいなので今回はプレーンな構成で構築してみます。


全体構成

画像



index.html

<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Leaflet Sample</title>
        <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>
        <link href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" rel="stylesheet" />

        <script src="https://unpkg.com/@ngageoint/leaflet-geopackage@3.0.3/dist/leaflet-geopackage.min.js"></script>

        <link href="css/style.css" rel="stylesheet" />
    </head>
    <body>
        <div id="map"></div>
        <script src="js/app.js"></script>
    </body>
</html>

LeafletをCDNで読み込みます。

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

leaflet-geopackageをCDNで読み込みます。

<script src="https://unpkg.com/@ngageoint/leaflet-geopackage@3.0.3/dist/leaflet-geopackage.min.js"></script>

/css

style.css

html, body {
    height: 100%;
    padding: 0;
    margin: 0;
}

#map {
    z-index: 0;
    height: 100%;
}

/js

app.js

// MIERUNE Streets読み込み
const m_streets = new L.tileLayer(
    'https://api.maptiler.com/maps/jp-mierune-streets/256/{z}/{x}/{y}.png?key=[APIキー]',
    {
        attribution:
            '<a href="https://maptiler.jp/" target="_blank">&copy; MIERUNE</a> <a href="https://www.maptiler.com/copyright/" target="_blank">&copy; MapTiler</a> <a href="https://www.openstreetmap.org/copyright" target="_blank">&copy; OpenStreetMap contributors</a>',
    }
);

// MIERUNE Gray読み込み
const m_gray = new L.tileLayer(
    'https://api.maptiler.com/maps/jp-mierune-gray/256/{z}/{x}/{y}.png?key=[APIキー]',
    {
        attribution:
            '<a href="https://maptiler.jp/" target="_blank">&copy; MIERUNE</a> <a href="https://www.maptiler.com/copyright/" target="_blank">&copy; MapTiler</a> <a href="https://www.openstreetmap.org/copyright" target="_blank">&copy; OpenStreetMap contributors</a>',
    }
);

// MAP読み込み
const map = L.map('map', {
    center: [43.3179, 142.6308],
    zoom: 8,
    zoomControl: true,
    layers: [m_streets],
});

//背景レイヤ
const Map_BaseLayer = {
    'MIERUNE Streets': m_streets,
    'MIERUNE Gray': m_gray,
};

//レイヤ設定
L.control.layers(Map_BaseLayer, null).addTo(map);

//スケール設定
L.control
    .scale({
        imperial: false,
        maxWidth: 300,
    })
    .addTo(map);

// GeoPackage読み込み
L.geoPackageFeatureLayer([], {
    // GeoPackageファイル指定
    geoPackageUrl: './data/shop.gpkg',
    // レイヤ名指定
    layerName: 'shop',
    pointToLayer: function (feature, layer) {
        return L.circleMarker(layer, {
            color: '#014c86',
            radius: 3,
            weight: 1,
            opacity: 0.7,
            fill: true,
            fillColor: '#014c86',
            fillOpacity: 0.7
        });
    },
    onEachFeature: function (feature, layer) {
        const field =
            `fid: ${feature.properties.fid} <br>
            full_id: ${feature.properties.full_id} <br>
            osm_id: ${feature.properties.osm_id} <br>
            name: ${feature.properties.name} <br>
            shop: ${feature.properties.shop}`;
        layer.bindPopup(field);
    }
}).addTo(map);

GeoPackageを読み込んで表示します。

// GeoPackage読み込み
L.geoPackageFeatureLayer([], {
    // GeoPackageファイル指定
    geoPackageUrl: './data/shop.gpkg',
    // レイヤ名指定
    layerName: 'shop',
    pointToLayer: function (feature, layer) {
        return L.circleMarker(layer, {
            color: '#014c86',
            radius: 3,
            weight: 1,
            opacity: 0.7,
            fill: true,
            fillColor: '#014c86',
            fillOpacity: 0.7
        });
    },
    onEachFeature: function (feature, layer) {
        const field =
            `fid: ${feature.properties.fid} <br>
            full_id: ${feature.properties.full_id} <br>
            osm_id: ${feature.properties.osm_id} <br>
            name: ${feature.properties.name} <br>
            shop: ${feature.properties.shop}`;
        layer.bindPopup(field);
    }
}).addTo(map);


簡易ローカルサーバーで確認してみます。

python -m http.server 8000


表示されました!

画像



LeafletでGeoPackageを読み込んで表示ができました!


LeafletでもGeoPackageを手軽に読み込むことができます。Webアプリケーションでも読めたりするので、GeoPackage好きなかたはゼヒお試しください!

今後、webpackで構築できるようにしたり、OpenLayersやMapbox GL JSのプラグインを構築できたらおもしろいなと思ったりしました。


ちなみに、以前の記事、「Try #051 – 色々なマップライブラリでポイント表示数の限界を探ってみた」のように、GeoPackageでも5万件の表示を検証してみましたが、GeoJSONと表示の重さは変わらなかったのでLeaflet側の限界なのかなと思いました…



Leafletについて、他にも記事を書いています。よろしければぜひ。
tags - Leaflet



book

Q&A