LoginSignup
5
2

More than 3 years have passed since last update.

leaflet.jsの日本語チュートリアルをやってみた。

Posted at

leaflet.jsを業務で使う事になったので調査。

埼玉大学谷謙二研究室さんが公開してくれている日本語のチュートリアル( http://ktgis.net/service/leafletlearn/index.html )が分かりやすかったので、やってみた。

なお、公式チュートリアル( https://leafletjs.com/examples.html )も存在するが、今回は触れてない。

learn_leaflet.html

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title>埼玉大学谷謙二研究室さんが公開してくれているleaflet.jsの日本語チュートリアルをやってみた</title>
        <link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.0/dist/leaflet.css" />
        <script src="https://unpkg.com/leaflet@1.3.0/dist/leaflet.js"></script>

        <style>
            /*紫色のアイコンのCSS  */
            .icon1 {
                width: 20px !important;
                height: 20px !important;
                border-radius: 10px;
                border: 3px solid #fdfdfd;
                box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.8);
                background-color: rgb(204, 51, 166);
            }

            /*茶色のアイコンのCSS  */
            .icon2 {
                width: 20px !important;
                height: 20px !important;
                border-radius: 10px;
                border: 3px solid #fdfdfd;
                box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.8);
                background-color: rgb(204, 125, 51);
            }

            /* 作成するdivのCSS */
            .infostyle {
                border: solid 1px;
                background-color: azure;
                border-radius: 10px;
                opacity: 0.8;
                padding: 5px;
                font-size: 15px;
                color: black;
            }
        </style>

        <script>
            // 定数:地図URL
            const MAP_URL_STD    = 'https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png';  // 地理院地図・標準地図タイル
            const MAP_URL_PALE   = 'http://cyberjapandata.gsi.go.jp/xyz/pale/{z}/{x}/{y}.png';  // 地理院地図・淡色地図タイル
            const MAP_URL_OPEN   = 'http://tile.openstreetmap.jp/{z}/{x}/{y}.png';  // オープンストリートマップのタイル
            const MAP_URL_RELIEF = 'http://cyberjapandata.gsi.go.jp/xyz/relief/{z}/{x}/{y}.png';  // 地理院地図・色別標高図タイル
            const MAP_URL_HILL   = 'http://cyberjapandata.gsi.go.jp/xyz/hillshademap/{z}/{x}/{y}.png';  // 地理院地図・陰影起伏図タイル

            // 定数:地図URLに紐づくaタグの属性
            const ATTR_URL_STD  = "<a href='https://maps.gsi.go.jp/development/ichiran.html' target='_blank'>地理院タイル</a>";  // 地理院地図
            const ATTR_URL_PALE = "<a href='http://portal.cyberjapan.jp/help/termsofuse.html' target='_blank'>地理院タイル</a>";  // 地理院地図
            const ATTR_URL_OPEN = "<a href='http://osm.org/copyright' target='_blank'>OpenStreetMap</a> contributors";  // オープンストリートマップ

            // 定数:座標
            const COORD_BASE              = [35.40     , 136];  // 初期位置
            const COORD_SAITAMA_UNIV      = [35.8627   , 139.6072];  // 埼玉大学
            const COORD_SAKURA_KUYAKUSHO  = [35.8561   , 139.6098];  // 桜区役所
            const COORD_KITAURAWA_STA     = [35.871986 , 139.645908];  // 北浦和駅
            const COORD_ROUTE             = [[35.865465, 139.60734], [35.870404, 139.6249], [35.870195, 139.6320], [35.871047, 139.6447], COORD_KITAURAWA_STA];  // 北浦和駅~埼玉大学の道案内
            const COORD_SAITAMA_UNIV_SITE = [[35.864891, 139.605503], [35.865969, 139.6088], [35.865378, 139.6097], [35.863309, 139.609559], [35.858996, 139.609709], [35.858248, 139.608722], [35.859813, 139.6053], [35.864248, 139.6056], [35.864891, 139.605503]];  // 埼玉大学の敷地
            const COORD_STOREs = [  // コンビニ一覧
                { pos: [35.8645472, 139.6048663], name: "セブンイレブン浦和埼玉大学店" },
                { pos: [35.8689857, 139.6086909], name: "セブンイレブンさいたま大久保店" },
                { pos: [35.871305, 139.6128431], name: "ファミリーマート浦和上大久保店" },
                { pos: [35.8665389, 139.6133905], name: "ミニストップさいたま上大久保店" },
                { pos: [35.8650306, 139.6070633], name: "ローソン埼玉大学店" }
            ];

            // クラス:オーバレイするグリッド線(タイル座標(z,x,y))をGridLayerで表示するためのクラス
            var GridLayerClass = L.GridLayer.extend({
                createTile: function (coords) {
                    //div要素でタイルを作成
                    var tileDiv = L.DomUtil.create('div', '');
                    tileDiv.setAttribute("style", "border: solid 1px");
                    //タイル要素の中にzxyを表示するdiv要素を作成
                    var coordsDiv = L.DomUtil.create('div', '', tileDiv);
                    coordsDiv.setAttribute("style", "position:absolute; background-color:white; padding:5px; border:solid 1px; left:10px; top:10px; font-size:15px;");
                    coordsDiv.innerHTML = "z / x / y = " + coords.z + " / " + coords.x + " / " + coords.y;
                    return tileDiv;
                },
            });

            // 変数:地図オブジェクトと線オブジェクトは各関数で使うためグローバル変数にしておく
            var map;
            var pline;

            //
            // 画面表示時の初期処理
            // - 各チュートリアルの内容を本関数に集約したよ
            //
            function init() {
                // -------------------- 基本オブジェクトの作成 --------------------
                map = L.map('mapcontainer', {
                    zoomControl: false
                });

                // -------------------- 初期状態(地図の中心・ズームレベル) --------------------
                map.setView(COORD_BASE, 5);

                // -------------------- レイヤー(基本地図・切替地図・オーバレイ地図) --------------------
                //基本地図:標準地図タイル
                L.tileLayer(MAP_URL_STD, { attribution: ATTR_URL_STD }).addTo(map);
                //切替地図:標準地図タイル、淡色地図タイル、オープンストリートマップ)
                var gsi     = L.tileLayer(MAP_URL_STD , { attribution: ATTR_URL_STD });
                var gsipale = L.tileLayer(MAP_URL_PALE, { attribution: ATTR_URL_PALE });
                var osm     = L.tileLayer(MAP_URL_OPEN, { attribution: ATTR_URL_OPEN });
                var baseMaps = {
                    "地理院地図": gsi,
                    "淡色地図": gsipale,
                    "オープンストリートマップ": osm
                };
                //オーバレイ地図:色別標高図タイル、陰影起伏図タイル、グリッド線
                var gsirelief         = L.tileLayer(MAP_URL_RELIEF, { opacity: 0.7, maxNativeZoom: 15, attribution: ATTR_URL_STD });
                var gsirehillshademap = L.tileLayer(MAP_URL_HILL  , { opacity: 0.5, maxNativeZoom: 16, attribution: ATTR_URL_STD });
                var zxyLayer          = new GridLayerClass();
                var overlayMaps = {
                    "色別標高図": gsirelief,
                    "陰影起伏図": gsirehillshademap,
                    "XYZ": zxyLayer
                };
                // 画面にセット
                L.control.layers(baseMaps, overlayMaps).addTo(map);
                gsi.addTo(map);  // ラジオボタンを選択状態にするために必要

                // -------------------- スケール(右下) --------------------
                L.control.scale({
                    maxWidth: 200,
                    position: 'bottomright',
                    imperial: false
                }).addTo(map);

                // -------------------- ズーム(左下、基本オブジェクト作成時にzoomControl:falseとする必要あり) --------------------
                L.control.zoom({
                    position: 'bottomleft'
                }).addTo(map);

                // -------------------- マーカー・ポップアップ・アイコン --------------------
                // アイコンオブジェクト
                var myIcon1 = L.divIcon({ className: 'icon1', iconAnchor: [13, 13] });  // アンカー:中央
                var myIcon2 = L.divIcon({ className: 'icon2', iconAnchor: [0, 0] });  // アンカー:左上
                // ポップアップあり、アイコンあり
                var popup1 = L.popup({ maxWidth: 550 }).setContent("埼玉大学です<br><img src='su.jpg' width='500' height='375'>");
                var popup2 = L.popup().setContent("桜区役所です");
                L.marker(COORD_SAITAMA_UNIV,  { icon: myIcon1 }).bindPopup(popup1).bindTooltip("埼玉大学").addTo(map);
                L.marker(COORD_SAKURA_KUYAKUSHO, { icon: myIcon2 }).bindPopup(popup2).bindTooltip("桜区役所").addTo(map);
                // ポップアップなし、アイコンなし
                //L.marker(COORD_SAITAMA_UNIV,  {title:"埼玉大学", draggable:true}).addTo(map);
                //L.marker(COORD_SAKURA_KUYAKUSHO, {title:"桜区役所"}).addTo(map);

                // 事前作成した複数のマーカーを表示
                var bound = L.latLngBounds(COORD_STOREs[0].pos, COORD_STOREs[0].pos);
                for (var num in COORD_STOREs) {
                    var mk    = COORD_STOREs[num];
                    var popup = L.popup().setContent(mk.name);
                    L.marker(mk.pos, { title: mk.name }).bindPopup(popup).addTo(map);
                    bound.extend(mk.pos);
                }
                // map.fitBounds(bound); // このマーカー群を初期表示位置にしたい場合はfitBoundsを使う(使わない場合はsetViewで設定した座標とズームが適用される)

                // -------------------- ベクタレイヤー(円・線・多角形、表示非表示) --------------------
                // 円(北浦和駅を中心に1000mごとの円を4つ作成する)
                var circleGroup = L.layerGroup();
                for (var i = 0; i < 4; i++) {
                    var r = i * 1000 + 1000;
                    circleGroup.addLayer(L.circle(COORD_KITAURAWA_STA, {
                            radius: r,
                            color: "#FF5555",
                            fill: false,
                            weight: 3
                        }).addTo(map)
                    );
                }
                // 円(地図の大きさに関係なく北浦和駅を円で囲む)
                var circleMarker = L.circleMarker(COORD_KITAURAWA_STA, {
                    radius: 20,
                    color: "#5555ff",
                    weight: 2,
                    fill: true,
                    fillColor: "#ffffff",
                    opacity: 0.5
                }).addTo(map);
                // 線(北浦和駅から埼玉大学までの道路)
                polyline = L.polyline(COORD_ROUTE, {
                    color: 'blue',
                    weight: 5,
                    bubblingMouseEvents: false  // イベントがmapオブジェクトに連鎖するのを防ぐ
                }).addTo(map);
                // 線(onLineClick関数で使うので空座標で一旦登録しておく)
                pline = L.polyline([], {
                    color: 'blue',
                    weight: 5,
                    bubblingMouseEvents: false  // イベントがmapオブジェクトに連鎖するのを防ぐ
                }).addTo(map)
                // 多角形(埼玉大学の敷地)
                var polygon = L.polygon(COORD_SAITAMA_UNIV_SITE, {
                    color: 'green',
                    weight: 2,
                    fill: true,
                    fillColor: 'green',
                    opacity: 0.5
                }).addTo(map);
                // 各ベクタレイヤをオブジェクトにまとめて、画面にセット
                var overlay = {
                    "polyline": polyline,
                    "Circle": circleGroup,
                    "CircleMarker": circleMarker,
                    "polygon": polygon
                }
                L.control.layers(null, overlay).addTo(map);

                // -------------------- 地図画面上にDiv要素の追加(左上、この例ではマウス移動した時の座標を表記) --------------------
                var latloninfo = L.control({ position: "topleft" });
                latloninfo.onAdd = function (map) {
                    //divを作成(最初は非表示、div上のとmousemoveイベントがmapに連鎖しないように設定)
                    this.ele = L.DomUtil.create('div', "infostyle");
                    this.ele.id = "latlondiv";
                    this.ele.style.visibility = "hidden";
                    this.ele.onmousemove = function (e) { e.stopPropagation() };
                    return this.ele;
                };
                latloninfo.addTo(map);

                // -------------------- イベント(click・mousemove) --------------------
                map.on('mousemove', onMapMousemove);
                map.on('click', onMapClick);
                pline.on('click', onLineClick);
            }

            //
            // 地図上のクリック
            // - クリック地点の座標にマーカーを追加
            // - マーカーがクリックされた場合は、onMarkerClick()を呼び出し
            // - クリックを繰り返すと線を引き続ける
            //
            function onMapClick(e) {
                L.marker(e.latlng).on('click', onMarkerClick).addTo(map);
                pline.addLatLng(e.latlng);
            }

            //
            // マーカーのクリック
            // - クリックされたマーカーを地図のレイヤから削除する
            //
            function onMarkerClick(e) {
                map.removeLayer(e.target);
            }

            //
            // 線のクリック
            // - クリックされた線を削除
            function onLineClick(e) {
                pline.setLatLngs([]);
            }

            //地図上を移動した際にdiv中に緯度経度を表示
            function onMapMousemove(e) {
                var box = document.getElementById("latlondiv");
                var html = "緯度:" + e.latlng.lat.toFixed(6) + "<br>" +
                           "経度:" + e.latlng.lng.toFixed(6);
                box.innerHTML = html;
                box.style.visibility = "visible";
            }

        </script>

    </head>

    <body onload="init()">
        <!-- 全画面表示するためにstyle設定 -->
        <div id="mapcontainer" style="position:absolute; top:0; left:0; right:0; bottom:0;"></div>
    </body>

</html>

5
2
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
5
2