Leaflet
読んでみてください。
DjangoでMapにPlotするにはどうすればよいのか、ということで調べてみてLeafletを知った。
Djangoがどうというより、javascriptの話。Google Mapと同じようなものか?
動的なPLotは現状難しいが、事前にPointを登録したJSONファイル(GeoJSON)を用意するだけで複数のPointをPlotできる。
GeoJSON
- type: データの種類(FeatureCollection, Feature, Point, LineString, Polygonなど)
- geometry: 座標情報(経度・緯度の順)
- properties: その場所に紐づく属性情報(名称、数値、メタデータなど)
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"title": "広島平和記念公園",
"marker-symbol": "park",
"description": "世界遺産に登録されています。"
},
"geometry": {
"type": "Point",
"coordinates": [
132.4530,
34.3934
]
}
},
{
"type": "Feature",
"properties": {
"title": "広島城",
"marker-symbol": "castle",
"description": "「鯉城」と呼ばれる城です。"
},
"geometry": {
"type": "Point",
"coordinates": [
132.4572,
34.3995
]
}
}
]
}
views
JSONファイルを読んでTemplateに渡すだけ。
def get(self,request):
json_path = os.path.join(settings.BASE_DIR, 'json/geojson.json')
with open(json_path, 'r', encoding='utf-8') as f:
json_data = json.load(f)
context = {
'data': json_data,
}
template
ヘッダーでCDNのLeafletのファイルや外部javascriptファイル(app.js)を読み込む。
{% load static %}
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin="" />
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>
<script src="{% static 'map/app.js' %}"></script>
json_scriptフィルターでJsonをHTMLに埋め込んで、javascriptで読めるようにする。
{{ data|json_script:"my-geojson-data" }}
javasctipt
app.jsというファイルを用意する。
document.addEventListener('DOMContentLoaded', function () {
// 1. 地図の初期化 (divのid="map"を指定, 緯度・経度・ズームレベル)
const map = L.map('map').setView([34.42181043001448, 132.45143119236275], 12);
// 2. 背景タイルの設定 (OpenStreetMapを利用)
// zoomの最大値を登録
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '© OpenStreetMap contributors'
});
// 埋め込んだJSONファイルを取り出す
var jsonElement = document.getElementById('my-geojson-data');
if (jsonElement) {
var geojsonFeature = JSON.parse(jsonElement.textContent);
if (typeof geojsonFeature === 'string') {
geojsonFeature = JSON.parse(geojsonFeature);
}
}
//Point Plot
L.geoJSON(geojsonFeature, {
pointToLayer: function (feature, latlng) {
// properties にある marker-symbol を取得してアイコンを切り替える処理
var symbol = feature.properties['marker-symbol'];
return L.marker(latlng, {
icon: L.icon({
iconUrl: '/media/mapimg/' + symbol + '.svg'
})
});
},
//Pointのmessageを設定
onEachFeature: function (feature, layer) {
if (feature.properties && feature.properties.title) {
// ポップアップに名前と説明を表示
var popupContent = "<b>" + feature.properties.title + "</b><br>" + feature.properties.description;
layer.bindPopup(popupContent);
}
}
}).addTo(map);
});
プロパティはアイコンサイズとか色とか設定できるようだけど、GeoJSON仕様のMarkerファイルを使うと設定が無効みたいなので省略した。
よくわからないところも多いけど、とりあえずJSONファイルさえ用意すれば仲間内への連絡などに使えそう。