Cette dépêche va présenter une méthode pour afficher sur un site personnel les traces, récits et photographies de balades (pédestres, cyclistes par exemple).
Comme le contenu à afficher est diversifié (texte, photographies, cartes), la solution retenue sera un blog. Dans un soucis de sobriété numérique, le site sera sans base de données.
Pour l'aspect esthétique, la barre de navigation et les cartes seront situées dans la partie gauche des pages et surtout, la carte ne bougera pas avec la navigation dans la page.
Sommaire
- 1 - Préparation de pelican
- 2 - Peaufinage de base
- 3 - Gestion cartographique
- 4 - Gestion des photographies associées à notre cartographie
- 5) Dernières modifications
- 6) Conclusion
N'ayant pas trouvé d'alternative libre à Polarstep, la solution retenue se base sur les briques logicielles libres suivantes :
- un moteur de blog static : pelican (AGPL v3.0)
- des thèmes pour le blog
- des bibliothèques cartographiques : leaflet (BSD 2)
1 - Préparation de pelican
Pelican propose d'écrire chaque billet de blogs dans un fichier texte indépendant (au format markdown ou reStructuredText).
Pelican les convertit en html et l'organisation du site ainsi généré (catégories, mots-clefs, archivage) se fait par le biais de gabarits (qui sont dans un sous-répertoire templates
)
a) Le moteur
L'installation ne sera pas développée ici, pelican étant disponible dans de nombreuses distributions.
Il faut créer la structure de travail (dans le répertoire personnel de notre choix) :
pelican-quickstart
b) Installation du thème graphique
En allant sur le dépôt des thèmes de pelican, il est possible de trouver le style graphique qui nous convient le mieux.
Nous allons utiliser le thème pelican-blue (sous licence MIT 2.0), qui a l'avantage d'être simple, et commençons son installation :
- création du répertoire
theme
dans notre structure de travail - décompression de l'archive du thème dans le répertoire « theme »
- modification du fichier
pelicanconf.py
pour configurer notre site. Il faut adapter quelques variables :
SITENAME = 'Mon blog'
SITEDESCRIPTION = 'Mes souvenirs de vacances'
THEME = "./theme/pelican-blue"
STATIC_PATHS = ['images', 'gpx']
- modifications propres au thème. Souvent l'auteur d'un thème propose de le personnaliser à partir de variables déclarées dans le fichier de configuration.
c) Écriture du premier billet
On va créer notre premier billet
Title: Première sortie
Date: 2025-05-01
Modified: 2025-05-01
Category: Lieux
Slug: depart
Tags: bonjour, balade
Bonjour tout le monde ! Quelle chouette sortie j'ai faite.
d) Génération de notre site
On lance la première compilation :
make clean
make html
On peut voir le résultat :
- soit en ouvrant directement le fichier index.html (présent dans le répertoire
output
) - soit en lançant un mini serveur web (
make serve
) et lancer son navigateur web à l'adressehttp://localhost:8000/
Pour plus de renseignements sur pelican, je vous invite à vous rendre sur la documentation du projet.
2 - Peaufinage de base
On va maintenant nettoyer le code des gabarits, en supprimant les choses que l'on trouve inutiles ou qui nous déplaisent. Tout se passe dans le répertoire templates
de notre thème.
- il y a les fichiers analytics.html et disqus.html
- une recherche par mot nous informe des éventuelles références à Google, Twitter, Facebook
On supprime les parties qui ne nous conviennent pas.
3 - Gestion cartographique
Nous attaquons désormais notre objectif : rendre visibles sur des cartes des fichiers de trace.
a) Gestion des cartes
On va maintenant configurer la gestion des cartes, par l'intermédiaire de leaflet. Comme l'indique sa page wikipédia, leaflet est très largement utilisé et très pratique.
On va donc
- le télécharger,
- le décompresser dans le répertoire
static
de notre thème - modifier les entêtes de nos gabarits (cela se fait le plus souvent dans le fichier
base.html
) pour y ajouter au niveau<head>
les références à leaflet :
<link rel="stylesheet" href="{{ SITEURL }}/theme/leaflet/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin=""/>
<script src="{{ SITEURL }}/theme/leaflet/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>
Comme on a récupéré en local les fichiers, on met des chemins propres à notre arborescence (via {{ SITEURL }}/theme/
).
b) Gestion des fichiers de trace (gpx)
Elle va se faire par l’intermédiaire d'un module supplémentaire https://github.com/mpetazzoni/leaflet-gpx (BSD 2).
De la même manière qu'on a intégré dans nos entêtes l'intégration de leaflet, nous allons ajouter une ligne pour faire référence à leaflet-gpx (bien vérifier le nom du fichier javascript) :
<script src="{{ SITEURL }}/theme/leaflet-gpx/gpx.js"></script>
Par rapport à la documentation officielle, on retire l'attribut defer (puisque nous utilisons les fichiers locaux et non distants).
Pour tester notre environnement, on va déposer dans notre répertoire gpx
un fichier de trace, puis on va ajouter dans notre billet les éléments de cartographie de notre voyage :
<div id="map" style="width: 600px; height: 400px;"></div>
<script>
var map = L.map('map');
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: 'Carte et données : <a href="http://www.osm.org">OpenStreetMap</a>'
}).addTo(map);
var gpx = '/gpx/FICHIER.gpx';
new L.GPX(gpx, {async: true}).on('loaded', function(e) {
map.fitBounds(e.target.getBounds());
}).addTo(map);
</script>
On regénère notre site web, et on peut visualiser notre billet
Globalement, ça fait le boulot.
Mais on peut améliorer la chose : on peut par exemple cacher les marques de début et de fin d'itinéraire en insérant la ligne suivante après le async: true
markers: {startIcon: null, endIcon: null, }
Mais surtout, nous souhaitons que pelican génère automatiquement la partie consacrée au fichier de trace (alors que dans notre test, nous avons dû l'ajouter nous-même) !
c) Modification des gabarits
Si l'on veut simplement ajouter notre fichier de trace et que notre gabarit le traite, on va ajouter cette information dans les entêtes de notre fichier markdown ! En effet pelican permet de créer des variables qui seront utilisables dans nos gabarits.
Nous allons donc créer et utiliser une variable (qui s'appellerait… Gpx
par exemple), qui stockera le nom du fichier gpx à afficher (les chemins sont relatifs à notre site web)
Title: Première sortie
Date: 2025-05-01
Modified: 2025-05-01
Category: Lieux
Gpx: /gpx/monfichier.gpx
Slug: depart
Tags: bonjour, balade
Nous modifions ensuite notre gabarit article.html
pour qu'il génère la carte à partir de notre variable.
Pelican est très souple : basé sur Jinja2, il permet les boucles, les conditions et les variables.
Tous les éléments qu'il utilise sont insérés dans des accolades. Le fonctionnement est facilement lisible et compréhensible.
On va donc conditonner (avec if
) l'insertion de leaflet.
{% if article.gpx %}
<div id="map" style="width: 600px; height: 400px;"></div>
<script>
var map = L.map('map');
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: 'Carte et données : <a href="http://www.osm.org">OpenStreetMap</a>'
}).addTo(map);
var gpx = '{{ article.gpx }}';
new L.GPX(gpx, {async: true,
markers: {startIcon: null, endIcon: null, }
}).on('loaded', function(e) {
map.fitBounds(e.target.getBounds());
}).addTo(map);
</script>
{% endif %}
Bien entendu, nous supprimons ces références du fichier markdown correspondant à notre billet de test.
On regénère notre site web, et on peut visualiser notre billet… qui n'a pas changé : tout fonctionne. Pour chacune de nos sorties, il suffit donc d'indiquer le fichier de trace dans les entêtes pour que la carte soit insérée automatiquement dans notre billet.
Passons maintenant à l'intégration de nos photos.
4 - Gestion des photographies associées à notre cartographie
Nous avons besoin :
- d'une image
- de ses coordonnées géographiques (latitude et longitude)
Pour cela, nous allons procéder de la même manière que pour le fichier trace : nous allons créer et utiliser des variables dans les entêtes des fichiers markdown.
a) Fichier des billets
Nous modifions encore une fois les entêtes en ajoutant autant d'informations (image, latitude et longitude) que de photos à afficher en miniatures.
Title: Première sortie
Date: 2025-05-01
Modified: 2025-05-01
Category: Lieux
Gpx: /gpx/monfichier.gpx
Slug: depart
Img: /images/image1.jpg
Lat: 49.895517
Lon: 2.295983
Img: /images/image2.jpg
Lat: 49.89443
Lon: 2.30137
Tags: bonjour, balade
On remarque ici que l'on a mis plusieurs images avec les mêmes noms de variables.
b) Modification des gabarits
Nous allons ensuite modifier les gabarits de pelican pour qu'ils positionnent des miniatures des photos sur notre trajet.
Nous allons à nouveau modifier notre fichier article.html
, en y ajoutant (à la suite de notre précédente modification, dans la condition {% if article.gpx %}
) le code suivant :
Nous commençons par indiquer l'icône qui s'affichera sur la carte à chaque photo mise en valeur
var MonIcone = L.icon({
iconUrl: '/images/app-photo.png',
iconSize: [36, 36]
});
Puis nous codons l'affichage du marqueur (qui sera géré par leaflet).
{% if article.img %}
{% if article.img is string %}
imageTxt = 'Description';
L.marker([{{ article.lat }}, {{ article.lon }}], {icon: MonIcone}).bindPopup(imageTxt + '<br><img src="{{ article.img }}" width="200px"><a href="#bal5">plus de détail</a>').addTo(map);
{% else %}
{% for n in range(article.img| length) %}
imageTxt = 'Description';
L.marker([{{ article.lat[n] }}, {{ article.lon[n] }}], {icon: MonIcone}).bindPopup(imageTxt + '<br><img src="{{ article.img[n] }}" width="200px"><a href="#bal5">plus de détail</a>').addTo(map);
{% endfor %}
{% endif %}
La difficulté réside dans la gestion des éléments répétitifs :
- s'ils sont plusieurs, on peut utiliser les méthodes python des listes.
- s'il n'y en a qu'un seul, cette méthode renvoie toutes les lettres de notre variable ! Il a donc fallu tester si celle-ci est une chaine de caractères ou une liste.
Les choix sont ici purement personnels ou démonstatifs :
- on a laissé une variable imageTxt en dur, elle pourrait être passée dans les entêtes de nos fichiers markdown
- le texte du popup peut être adapté (on pourrait y ajouter un lien direct vers notre image par exemple)
- le lien (ancre) est à créer dans notre fichier markdown
- la taille de l'image du popup est en dur (on peut passer par une feuille de style css)
On regénère notre site web, et on peut visualiser notre billet :
Et lorsqu'on clique sur une icône d'appareil photo, on voit bien notre popup :
c) Gestion des photographies
Comme indiqué plus haut, la taille des miniatures affichées peut se gérer :
- par CSS
- ou créer des miniatures (avec
imagemagick
) pour diminuer la charge de notre serveur (afficher une photo de 3000 pixels à 200 pixels n'est pas optimal). Dans ce cas, il suffira d'adapter notre gabarit pour lui indiquer où aller chercher les petites images (/images/miniatures/
par exemple)
Par contre, le point le plus compliqué est la gestion des coordonnées des photographies : il faut les rentrer à la main !
Pour les photographies qui n'intègrent pas les coordonnées dans leurs métadonnées, il n'y a pas d'autre solution que d'aller chercher sur une carte (openstreetmap par exemple) et de trouver le lieu de la prise de vue et de repérer les coordonnées.
Pour les photographies qui contiennent leurs coordonnées géographiques, on peut utiliser l'outil
exiftool
pour les récupérer. On peut éventuellement faire un script bash qui affiche les lignes d'entête pour notre billet (on n'a plus qu'à les recopier ou les rediriger vers un fichier texte) :
for photo in $(ls ./content/images);
do
echo ""
echo "Img: /images/"$photo
LAT=$(exiftool -n -s3 -gpslatitude ./content/images/$photo)
echo "Lat: "$LAT
LONG=$(exiftool -n -s3 -gpslongitude ./content/images/$photo)
echo "Lon: "$LONG
done
Nous avons utilisé les options -n
qui affichent les valeurs numériques au format décimal (celui utilisé par openstreetmap pour les coordonnées) et -s3
pour avoir la valeur du champ sans le nom de son attribut.
5) Dernières modifications
Nous venons de voir les différentes techniques qui permettent d'avoir le rendu que nous souhaitions. Et le résultat est déjà agréable à regarder.
Nous pourrions nous arrêter ici, mais vous voulons que la carte reste en permanence dans le menu latéral. La solution est de la mettre dans une balise <aside>
.
a) Modifier les gabarits
Notre thème comporte déjà une telle balise : elle est dans le fichier base.html
… ce qui signifie qu'il ne peut pas voir les informations sur les articles (donc nos entêtes) !
La solution va donc consister à déplacer, à l'intérieur du fichier article.html
, tout notre code dans une section (que nous appellerons mamap :
{% block mamap %}
Mettre ici tout le code sur notre gestion cartographique
{% endblock %}
Et dans le fichier base.html
, on va insérer à l'intérieur des balises <aside>
son appel (qui ne tient que sur deux lignes) :
{% block mamap %}
{% endblock %}
b) Ajuster les feuilles de style
Il faut surcharger le comportement de la carte gérée par leaflet :
.leaflet-container {
width: 400px;
height: 300px;
max-width: 100%;
max-height: 100%;
margin: auto;
}
Et vérifier que les largeurs de la carte, et de <aside>
soient compatibles.
Le résultat avec nos dernières modifications est désormais le suivant
6) Conclusion
Il est temps de finir cette dépêche, dans laquelle nous avons pu découvrir la souplesse et la richesse des gabarits gérés avec jinja2, ainsi que la facilité d'utilisation de leaflet.
Désormais, dans notre flux de travail, nos répertoires sont organisé ainsi :
content
+ gpx : les fichiers de trace
+ images : les photos que l'on veut afficher sur notre blog
fichierXX.md : les billets
output : notre site web (généré par pelican)
theme
+ pelican-blue : le thème choisi
+ static
+ css
+ leaflet
+ leaflet-gpx
+ templates
Et la rédaction de nos billets consiste à :
- ajouter le fichier gpx de notre trace dans les entêtes
- ajouter les informations sur chaque photo que l'on veut voir (toujours dans les entêtes)
- écrire notre billet normalement (en y ajoutant éventuellement d'autres photos ou des ancres de navigation)
Cette dépêche démontre qu'il est possible d'avoir, avec les outils actuels, un rendu intéressant pour partager ses sorties. Et totalement utilisable en auto-hébergement.
Les outils utilisés sont très personnalisables et je vous invite à lire leurs documentations ou à parcourir leurs extensions respectives et de vous les approprier selon votre usage.
Malheureusement, la solution présentée ne conviendra qu'à une minorité d'utilisateurs. En effet, elle se base sur des éléments qui sont le plus souvent rendus invisibles (site web, transfert de fichiers, métadonnées) et elle est inutilisable sur téléphone.
# Alternative éventuelle: PiGallery2
Posté par Christophe . Évalué à 6 (+4/-0).
Le logiciel PiGallery2 est plutôt orienté album photo que blog, mais il permet aussi d'ajouter du texte, ainsi que des traces GPX, à un album donné.
Pour rajouter du texte, cela se fait en rajoutant un fichier Markdown dans le même répertoire que les photos. Dans ce fichier on peut alors insérer des marqueurs pour dire où le texte doit se trouver par rapport aux photos.
Si un fichier GPX est trouvé dans le répertoire, une trace sera ajoutée à la carte des emplacements des photos.
Donc au final, cela peut constituer une autre approche de présentation que celle présentée dans la dépêche, avec ses propre avantages et inconvénients.
# Merci pour le partage
Posté par raphj . Évalué à 4 (+2/-0). Dernière modification le 02 juin 2025 à 16:55.
et également merci à Christophe pour la mention de PiGallery2.
Je vais probablement me servir de tout ça comme source d'inspiration.
Ça tombe à pic : je suis justement en train de me préparer pour un petit voyage où je compte partager mes photos depuis un blog avec une carte interactive. Et je suis en train de programmer un truc pour ça, avec un peu de chance j'aurai fini à temps. Ça tombe tellement à pic que je me suis un instant demandé si je n'allais pas jeter une semaine de travail pour reprendre l'idée de ce journal telle quelle. Mais je vais persister.
Je n'ai pas nécessairement besoin de traces GPX (mais ce serait chouette de l'avoir), par contre l'idée serait d'avoir des articles de blog (des "étapes") dans lesquelles il y a des photos.
Sans Javascript, le site statique généré ressemblerait à un blog classique, mais avec Javascript, le visiteur pourra se balader sur une carte et dans une visionneuse, dans l'esprit « progressive enhancement » le plus fidèle. La visionneuse devrait permettre de se balader dans les descriptions et d'afficher les photos, avec une option pour rester dans la même étape ou pour traverser la visite entière. Les photos seront affichées avec un petit descriptif s'il est fournit.
Un flux RSS serait généré pour que les deux seules personnes au monde avec un lecteur RSS puissent être notifiées des mises à jour.
Le site serait généré à partir d'un dossier Nextcloud partagé publiquement (c'est du WebDAV très standard derrière, mais Nextcloud génère aussi des miniatures et je compte réutiliser ça au moins dans un premier temps). Un bouton importer irait interroger le dossier et stocker les infos dans une petite base SQLite à partir de laquelle le blog serait généré. Seuls les fichiers changés seraient réévalués, c'est aussi là que la base SQLite est justement utile, mais restant "sobre" comme le dit l'article.
Le dossier partagé contiendrait des fichiers Markdown avec front matter qui décrivent ces fameuses étapes, très compatible avec ce qu'attendrait un générateur de sites statiques tel qu'Hugo. Ces fichiers Markdown afficheraient des photos et ces photos peuvent contenir des données GPS. Dans le front matter des étapes, on pourrait définir une date, une localisation gps, voire un noeud OSM. Les localisations GPS des images seraient récupérées mais pourraient aussi être spécifiés dans les fichiers d'étape : ça permettra d'ajouter les localisation à la main directement dans le fichier d'étape sans devoir utiliser des outils complexes ou en ligne de commande, quitte à ajouter les localisations aux fichiers eux-mêmes dans un second temps.
Et par défaut, si la localisation manque pour une photo, c'est la localisation de l'étape qui sera utilisée, donc ça pourra ne pas être trop fastidieux au pire.
Nextcloud ayant un éditeur Markdown WYSIWYG, ou le dossier pouvant être synchronisé sur un appareil doté de l'éditeur markdown de son choix, le tout serait utilisable par quelqu'un qui n'est pas technique. Je le sais déjà, j'ai déjà un site de recettes reposant sur un système comme ça, mis à jour avec succès par quelqu'un d'autre que moi. Et si l'outil venait à disparaitre, le blog ne disparaîtrait pas avec puisqu'il serait entièrement consultable avec n'importe quel éditeur Markdown standard.
Bref, à suivre.
# EnVadrouille
Posté par nico4nicolas . Évalué à 6 (+4/-0).
Un peu à côté, car il n'y a pas la partie récit, un membre de LinuxFr a réalisé EnVadrouille. Il y a la galerie photos, la visualisation des traces, je trouve ça bien fait et simple d'utilisation. Seule la partie admin nécessite l'utilisation de php donc on retrouve cette idée de tout avoir en statique.
Je n'ai pas regardé plus que ça mais EnVadrouille semble fonctionner avec un système de plugins.
# Super
Posté par arnauld . Évalué à 5 (+4/-0).
Très intéressant, merci. J'aimerais trouver l'équivalent pour mon blog sous Hugo (inactif pour le moment, que des anciens posts).
J'avais écrit un billet concernant le logiciel Gpx-Animator https://github.com/gpx-animator/gpx-animator qui permet de faire une vidéo d'un tracé gpx en y insérant des photos géotaggées : https://arnauld.org/blog/posts/gpx-animator/
arnauld
# uMap
Posté par Colargol (Mastodon) . Évalué à 4 (+2/-0).
On peut aussi utiliser uMap. Il faut cependant héberger les images sur un autre serveur. Les traces gpx peuvent être affichées directement dans uMap.
Envoyer un commentaire
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.