Leafletを使った地図アプリを作る上で試行錯誤したことをメモとして書いています。その機能あるよなど、なにかあればぜひコメントください。
概要
やりたいこと
- leafletで表示中の地図に、KMLファイルの内容を表示したい。
- KMLファイルで表示した各要素をカスタマイズしたい。まずはポップアップの内容を編集したい。
結論
-
leaflet-kml
の中に使われている関数を一部コピーして、カスタマイズ、leaflet-kml
を上書きする。
使用するもの
- Leaflet
- leafletjsのKML表示プラグインleaflet-kml
- KMLの作成にはGoogle マイマップ、Google Earthを利用しています。
0,KMLファイルを作成する
スタート
とゴール
の2つのマーカーを立てたものを作りました。
Google Mymap | Google MymapからKMLファイルを書き出し |
---|---|
![]() |
![]() |
sample.kmlが完成。
1,KMLを表示する
単純にKMLファイルを読み込んで表示する
index.html
<!DOCTYPE html>
<html>
<head>
<title>Leaflet KML Example</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Leaflet CSS -->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" />
<!-- Leaflet JavaScript -->
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>
<!-- Leaflet-KML Plugin -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet-plugins/3.4.0/layer/vector/KML.js"></script>
</head>
<body>
<div id="map" style="height: 400px;"></div>
<script>
// Create a Leaflet map
var map = L.map('map').setView([0, 0], 2); // Set the initial map center and zoom level.
// Add a base layer (e.g., OpenStreetMap)
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
}).addTo(map);
// Load and display a KML file on the map
var kmlURL = 'sample.kml';
var kmlLayer = new L.KML(kmlURL, {
async: true,
}).addTo(map);
</script>
</body>
</html>
表示したもの。
2,ポップアップをカスタマイズ
マーカーをクリックした際に表示するポップアップに緯度経度座標を表示させます。
as-is | to-be |
---|---|
![]() |
![]() |
ポップアップを表示している関数(parsePlacemark)をコピー
Leaflet-KML Pluginのファイル、KML.jsの中でbindPopup
を検索。出てきた箇所を含む関数parsePlacemark
をごっそりコピー、自分で作ったindex.html
のLeaflet-KML Plugin
を読み込んだ直後に貼り付ける。
貼り付けの際、parsePlacemark:functionの部分をL.KML.parsePlacemark=functionに書き換える。
index.htmlの一部分を抜粋
// ↓こうなっていたものを
parsePlacemark:function (place, xml, style, options) { ...
// ↓ こうする
L.KML.parsePlacemark = function (place, xml, style, options) { ...
layer.bindPopupをカスタマイズ
layer.bindPopupの周辺にてGPS座標を取得、また、それらを表示するようにする。
index.htmlの一部を抜粋
var pointLatLang = layer.getLatLng(); // 追記: レイヤーから緯度経度座標を取得
var pointlatLngStr = "GPS: " + pointLatLang.lat + ", " + pointLatLang.lng; // 追記: 表示用の文字列にする
if (name) {
layer.on('add', function () {
layer.bindPopup('<h2>' + name + '</h2>' + descr + "<br>" + pointlatLngStr);// 編集: 表示用の文字列を文字列をポップアップに追記する
});
}
最終形
index.html
<!DOCTYPE html>
<html>
<head>
<title>Leaflet KML Example</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Leaflet CSS -->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" />
<!-- Leaflet JavaScript -->
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script>
<!-- Leaflet-KML Plugin -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet-plugins/3.4.0/layer/vector/KML.js"></script>
<script>
L.KML.parsePlacemark = function (place, xml, style, options) {
var h, i, j, k, el, il, opts = options || {};
el = place.getElementsByTagName('styleUrl');
for (i = 0; i < el.length; i++) {
var url = el[i].childNodes[0].nodeValue;
for (var a in style[url]) {
opts[a] = style[url][a];
}
}
il = place.getElementsByTagName('Style')[0];
if (il) {
var inlineStyle = this.parseStyle(place);
if (inlineStyle) {
for (k in inlineStyle) {
opts[k] = inlineStyle[k];
}
}
}
var multi = ['MultiGeometry', 'MultiTrack', 'gx:MultiTrack'];
for (h in multi) {
el = place.getElementsByTagName(multi[h]);
for (i = 0; i < el.length; i++) {
return this.parsePlacemark(el[i], xml, style, opts);
}
}
var layers = [];
var parse = ['LineString', 'Polygon', 'Point', 'Track', 'gx:Track'];
for (j in parse) {
var tag = parse[j];
el = place.getElementsByTagName(tag);
for (i = 0; i < el.length; i++) {
var l = this['parse' + tag.replace(/gx:/, '')](el[i], xml, opts);
if (l) { layers.push(l); }
}
}
if (!layers.length) {
return;
}
var layer = layers[0];
if (layers.length > 1) {
layer = new L.FeatureGroup(layers);
}
var name, descr = '';
el = place.getElementsByTagName('name');
if (el.length && el[0].childNodes.length) {
name = el[0].childNodes[0].nodeValue;
}
el = place.getElementsByTagName('description');
for (i = 0; i < el.length; i++) {
for (j = 0; j < el[i].childNodes.length; j++) {
descr = descr + el[i].childNodes[j].nodeValue;
}
}
var pointLatLang = layer.getLatLng();
var pointlatLngStr = "GPS: " + pointLatLang.lat + ", " + pointLatLang.lng;
if (name) {
layer.on('add', function () {
layer.bindPopup('<h2>' + name + '</h2>' + descr + "<br>" + pointlatLngStr);
});
}
return layer;
}
</script>
</head>
<body>
<div id="map" style="height: 400px;"></div>
<script>
// Create a Leaflet map
var map = L.map('map').setView([0, 0], 2); // Set the initial map center and zoom level.
// Add a base layer (e.g., OpenStreetMap)
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
}).addTo(map);
// Load and display a KML file on the map
var kmlURL = 'sample.kml'; // Replace with the path to your KML file
var kmlLayer = new L.KML(kmlURL, {
async: true,
}).addTo(map);
</script>
</body>
</html>