浜松のWEBシステム開発・スマートフォンアプリ開発・RTK-GNSS関連の開発はお任せください
株式会社シーポイントラボ
TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:静岡県浜松市中区富塚町1933-1 佐鳴湖パークタウンサウス2F

【JavaScript】Leaflet Drawプラグインで描画した図形の緯度経度を取得する

投稿が続いていますが、Leaflet Draw プラグインについてです。
今回は、描画した図形の緯度経度を取得する方法についてです。
直線や多角形の場合は各頂点の緯度経度を取得し、円やマーカーについては中心位置の緯度経度を取得します。

直線や多角形の各頂点の緯度経度を取得する方法については、以前も紹介した下記の記事を参考にさせていただきました。

Leafletにあれこれ描く – bl.ocks.org
http://bl.ocks.org/TetsuyaKimotsuki/0156c511e3217edf58beb206633308f8

円やマーカーの緯度経度の取得については、GitHub の Issues の記事を参考にしました。

when resize circle in leaflet draw I can’t get the new circle value lat lon radius · Issue #870 · Leaflet/Leaflet.draw · GitHub
https://github.com/Leaflet/Leaflet.draw/issues/870

 

サンプルコードは下記のとおりです。
今回重要なのは、図形を新規追加した時と編集した時に実行する setFeatureProperties 関数です。
下記のコードだと 37行目から最終行までです。
こちらの関数を図形追加時と編集時に呼び出すようにします。

const map = L.map('map', {
  center: [34.797345395117546, 137.5804696201213],
  zoom: 13,
  drawControl: false,
});
const tiles = L.tileLayer('https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png', {
  attribution: "<a href='https://maps.gsi.go.jp/development/ichiran.html' target='_blank'>地理院タイル</a>"
}).addTo(map);

// 図形描画ボタンをマップに追加
let drawnItems = new L.FeatureGroup();
map.addLayer(drawnItems);
let drawControl = new L.Control.Draw({
    edit: {
        featureGroup: drawnItems
    }
});
map.addControl(drawControl);

// 図形を新規作成した時
map.on(L.Draw.Event.CREATED, function (e) {
  drawnItems.addLayer(e.layer);
  e.layer.feature = e.layer.feature || {};
  e.layer.feature.properties = e.layer.feature.properties || {};
  e.layer.feature.type = "Feature";
  popup = e.layer.bindPopup("");
  setFeatureProperties(e.layer);
});

// 図形を編集した時
map.on(L.Draw.Event.EDITED, function (e) {
  e.layers.eachLayer(function (layer) {
    setFeatureProperties(layer);
  });
});

const setFeatureProperties = function (layer) {
  // 線と多角形と四角形
  if (layer instanceof L.Polyline) {
    var latlngs = layer._defaultShape ? layer._defaultShape() : layer.getLatLngs();
    if (latlngs.length >= 2) {
      var distance = 0;
      layer.feature.properties.latlng = [];
      for (var i = 0; i < latlngs.length - 1; i++) {
        distance += latlngs[i].distanceTo(latlngs[i + 1]);
      }
      layer.feature.properties.distance = distance.toFixed(2) + " m"; // ex. distance 3728.81 m

      // 緯度経度を取得
      latlngs.forEach((latlng, index) => {
        layer.feature.properties.latlng[index] = [latlng.lat, latlng.lng];
      });
    }
    layer.feature.properties.drawtype = L.Draw.Polyline.TYPE;
  }
  // 多角形と四角形
  if (layer instanceof L.Polygon) {
    var latlngs = layer._defaultShape ? layer._defaultShape() : layer.getLatLngs();
    var area = L.GeometryUtil.geodesicArea(latlngs);
    layer.feature.properties.area = L.GeometryUtil.readableArea(area, true); // ex. area 174.19 ha
    layer.feature.properties.drawtype = L.Draw.Polygon.TYPE;
    delete layer.feature.properties.distance;
  }
  // 四角形
  if (layer instanceof L.Rectangle) {
    layer.feature.properties.drawtype = L.Draw.Rectangle.TYPE;
    delete layer.feature.properties.distance;
  }
  // 円
  if (layer instanceof L.Circle) {
    layer.feature.properties.radius = layer.getRadius().toFixed(2) + " m"; // ex. radius 1097.02 m
    layer.feature.properties.latlng = [layer.toGeoJSON().geometry.coordinates[1], layer.toGeoJSON().geometry.coordinates[0]];
    layer.feature.properties.drawtype = L.Draw.Circle.TYPE;
  }
  // マーカー
  if (layer instanceof L.Marker) {
    layer.feature.properties.latlng = [layer.toGeoJSON().geometry.coordinates[1], layer.toGeoJSON().geometry.coordinates[0]];
    layer.feature.properties.drawtype = L.Draw.Marker.TYPE;
  }
  // popup 時の表示内容の差し替え
  var contents = "";
  for (var key in layer.feature.properties) {
    if (key != 'note' && key != 'drawtype' && key != 'latlng') {
      contents = contents + key + " " + layer.feature.properties[key] + "<br />";
    }
    if (key == 'latlng') {
      contents = contents + key + " " + JSON.stringify(layer.feature.properties[key]) + "<br />";
    }
  }
  layer.setPopupContent(contents);
};

まず、直線や多角形などの取得する緯度経度が複数ある場合は、下記のように記述します。

var latlngs = layer._defaultShape ? layer._defaultShape() : layer.getLatLngs();
if (latlngs.length >= 2) {
  latlngs.forEach((latlng, index) => {
    layer.feature.properties.latlng[index] = [latlng.lat, latlng.lng];
  });
}

なお、今回は layer.feature.properties.latlng という変数に値を配列で代入しています。

次に、円やマーカーなど、取得する緯度経度が 1つしかない場合の処理は下記のとおりです。

layer.feature.properties.latlng = [layer.toGeoJSON().geometry.coordinates[1], layer.toGeoJSON().geometry.coordinates[0]];

上記コードを実行すると、図形をクリックした時に表示される吹き出しに、緯度経度の項目が表示されるようになっています。
また、編集機能を使って描画した図形のサイズや位置を修正しても、問題なく変更が反映されていました。

図形によって書き方が変わるのでちょっと混乱しそうですが、分かりやすいサンプルコードを見つけられたおかげで思ったよりもすんなりと実装出来ました。

 

以上、Leaflet Draw プラグインを使って描画した図形の緯度経度を取得する方法についてでした。
ご参考になれば幸いです。

  • この記事いいね! (0)