feat: add GPX route rendering to trip map via leaflet-gpx

Adds leaflet-gpx@2.1.2 CDN script to map template, collects *.gpx
media files from the trip page, and renders them as teal polylines
beneath entry pins. Also fixes user/config/media.yaml to use the
required types: key so Grav's Media class correctly discovers .gpx
files. Map remains functional when no GPX files are present.
This commit is contained in:
2026-06-19 01:38:36 +02:00
parent 50a5f2d178
commit 86997cb878
2 changed files with 21 additions and 2 deletions
+2 -2
View File
@@ -1,4 +1,4 @@
gpx: types:
gpx:
type: file type: file
extensions: ['gpx']
mime: application/gpx+xml mime: application/gpx+xml
@@ -1,9 +1,17 @@
{% extends 'partials/base.html.twig' %} {% extends 'partials/base.html.twig' %}
{% block content %} {% block content %}
{% set trip_page = page.parent() %}
{% set tracker_page = grav.pages.find(page.parent().route ~ '/dailies') %} {% set tracker_page = grav.pages.find(page.parent().route ~ '/dailies') %}
{% set all_entries = tracker_page ? tracker_page.children.published() : [] %} {% set all_entries = tracker_page ? tracker_page.children.published() : [] %}
{% set gpx_urls = [] %}
{% for name, media in trip_page.media.all %}
{% if name|split('.')|last == 'gpx' %}
{% set gpx_urls = gpx_urls|merge([trip_page.url ~ '/' ~ name]) %}
{% endif %}
{% endfor %}
{% set map_entries = [] %} {% set map_entries = [] %}
{% for entry in all_entries %} {% for entry in all_entries %}
{% if entry.header.lat is not empty and entry.header.lng is not empty %} {% if entry.header.lat is not empty and entry.header.lng is not empty %}
@@ -28,6 +36,7 @@
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.min.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.min.css">
<script src="https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/leaflet@1.9.4/dist/leaflet.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/leaflet-gpx@2.1.2/gpx.min.js"></script>
<script> <script>
var ENTRIES = {{ map_entries|json_encode|raw }}; var ENTRIES = {{ map_entries|json_encode|raw }};
@@ -38,6 +47,16 @@ L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map); }).addTo(map);
// GPX route tracks
const gpxUrls = {{ gpx_urls|json_encode|raw }};
gpxUrls.forEach(url => {
new L.GPX(url, {
async: true,
polyline_options: { color: '#1F6B5A', weight: 2, opacity: 0.7 },
marker_options: { startIconUrl: null, endIconUrl: null, shadowUrl: null }
}).addTo(map);
});
if (ENTRIES.length === 0) { if (ENTRIES.length === 0) {
map.setView([20, 0], 2); map.setView([20, 0], 2);
var emptyDiv = document.createElement('div'); var emptyDiv = document.createElement('div');