DataViz

Composants de visualisation et gabarits

En bref

  • Pour qui : toute personne qui ajoute un graphique au portail (équipes du hackathon, rédacteurs de l'onglet DataViz).
  • Ce que vous trouverez : les 7 composants de graphique, une démo de chacun, le format JSON attendu et un squelette à copier dans une page .mdx.
  • Données utilisées : des agrégats réels du bucket SSP Cloud (écocompteurs, nuitées, hôtellerie, lits, catalogue des sites), cités sous chaque démo.
  • Mise à jour : 09/11/2026.

Ces composants dessinent des graphiques interactifs et accessibles directement dans une page du portail. Vous n'écrivez pas de code de dessin : vous préparez un petit fichier JSON, puis vous écrivez une seule balise dans la page.

Chaque graphique affiche un titre, une légende dès qu'il y a deux séries, la source, une info-bulle au survol (et au clavier), et un bouton « Voir les données » qui ouvre le tableau des valeurs.

Le chemin d'une donnée jusqu'au graphique

Diagramme

Comment lire : de gauche à droite, la donnée brute reste dans le bucket ; seul un agrégat (une somme, une moyenne, un comptage) est copié dans le portail, sous forme de JSON.

Jamais de données brutes ni personnelles

Le dossier docs/public est publié tel quel sur le site. N'y mettez que des agrégats (par mois, par commune, par catégorie). Aucune ligne individuelle, aucune adresse électronique, aucun numéro de téléphone, aucun identifiant. Le fichier des ventes de forfaits contient des données personnelles : uniquement des totaux.

Ajouter un graphique en 4 étapes

  1. Choisir la forme avec le tableau ci-dessous.
  2. Écrire le JSON au format du composant, dans docs/public/dataviz/<nom-de-page>/<nom>.json. Le plus simple est de le produire avec un script de docs/scripts/, pour pouvoir le recalculer.
  3. Insérer la balise dans la page, par exemple <LineChart src="/dataviz/ma-page/passages.json" />. Aucun import n'est nécessaire.
  4. Écrire la phrase « Comment lire » juste sous le graphique, puis contrôler : node scripts/check-mdx.mjs 09-dataviz/ma-page.mdx.

Choisir le bon graphique

La question du lecteurComposantExemple
Quelques chiffres à retenirKpiRowpassages comptés, nombre de compteurs
Comment ça évolue dans le temps ?LineChartpassages mensuels 2021-2026
Qui a le plus, qui a le moins ?BarChart horizontalcommunes les mieux dotées en lits
Comment se répartit un total, année après année ?BarChart empilénuitées des résidents et des non-résidents
Quand est-ce le plus chargé (jour × heure, année × mois) ?Heatmapnuitées par mois et par année
Au-dessus ou au-dessous d'une référence ?Heatmap ou ChoroplethMap en échelle divergenteécart à la moyenne
Deux mesures vont-elles ensemble ?ScatterPlotlits touristiques et manifestations
Où, sur le territoire, en valeur par commune ?ChoroplethMapsites recensés par commune
Où sont les lieux précis ?PointMapsites, compteurs, parkings

Comment lire : partez de la question que se pose le lecteur, pas des données disponibles. Un seul chiffre important se montre en KpiRow, pas en graphique.

Règles communes à tous les composants

  • src ou data : src est l'adresse d'un JSON servi depuis docs/public (elle commence par /, sans public). data reçoit le même objet écrit directement dans la page. Si les deux sont donnés, data l'emporte.
  • Titre, sous-titre et source viennent du JSON ; les attributs title, subtitle et source de la balise les remplacent si besoin.
  • Source obligatoire : le nom du fichier du bucket (par exemple Hébergements/Hébergements par commune.xlsx), et « (calcul : portail) » quand le chiffre est recalculé.
  • « (déduit) » dans le titre ou le nom de série pour toute valeur estimée ou calculée (écart, population présente, part…).
  • Couleurs : ne choisissez pas de couleur. Elles viennent d'une palette fixe, vérifiée pour le daltonisme et pour les modes clair et sombre. Au-delà de 3 groupes dans un nuage ou une carte, les suivants passent en gris « Autres ».
  • Nombres : écrivez des nombres bruts dans le JSON (1160000, pas "1,16 M"). Le composant les formate en français.
  • Au clavier : la touche Tab donne le focus au graphique, les flèches parcourent les valeurs, Échap ferme l'info-bulle. Les lecteurs d'écran annoncent chaque valeur.

KpiRow : chiffres clés

Chargement…

Comment lire : chaque tuile donne un ordre de grandeur et, en petit, sa période ou sa portée. Ces chiffres viennent des analyses des écocompteurs et de la capacité d'hébergement (Insee 2026).

Format JSON (value est affiché tel quel : formatez-le vous-même) :

JSONCode
{ "items": [ { "label": "Passages comptés", "value": "233 719 994", "hint": "du 01/01/2021 au 07/11/2026" }, { "label": "Écocompteurs", "value": "408", "hint": "avec au moins un jour de données" } ] }

Squelette à copier (les trois écritures sont équivalentes) :

ReactCode
<KpiRow src="/dataviz/ma-page/kpi.json" /> <KpiRow items={[{ label: "Lits touristiques", value: "81 348", hint: "902 établissements" }]} /> <KpiRow data={{ items: [{ label: "Communes", value: 513 }] }} />

LineChart : évolution dans le temps

Chargement des données…

Comment lire : chaque courbe est la somme des passages de tous les compteurs actifs ce mois-là. Survolez le graphique pour lire les deux valeurs d'un même mois. Le nombre de compteurs change dans le temps : une hausse peut venir d'un nouveau compteur.

Format JSON :

JSONCode
{ "title": "Passages mensuels comptés par les écocompteurs de l'Isère", "subtitle": "Somme de tous les compteurs actifs chaque mois", "x": ["2021-01", "2021-02", "2021-03"], "series": [ { "name": "Piétons", "values": [1216562, 1484952, null] }, { "name": "Cyclistes", "values": [437946, 555273, 759786] } ], "yLabel": "Passages par mois", "unit": "passages", "source": "Fréquentation/eco-compteur-Isère/comptages/historique_2021_2024.csv" }
  • x : libellés libres, ou dates ISO (2024, 2024-07, 2024-07-14) ; les dates sont alors écrites en français (« juillet 2024 ») et les graduations placées en début d'année ou de mois.
  • null dans values : un trou dans les données, la courbe est coupée (jamais reliée à travers le vide).
  • Options : zero: false pour ne pas partir de 0 (températures par exemple) ; area: true pour un aplat léger sous une courbe unique.
  • 8 séries au maximum ; au-delà de 4, préférez plusieurs petits graphiques.
ReactCode
<LineChart src="/dataviz/ma-page/evolution.json" /> <LineChart src="/dataviz/ma-page/evolution.json" height={200} title="Titre remplacé" />

BarChart : comparer des quantités

Barres groupées

Chargement des données…

Comment lire : pour chaque jour, la barre bleue donne les piétons et la barre orange les cyclistes, en passages moyens par compteur. Les piétons culminent le samedi, les cyclistes en semaine.

Barres horizontales

Chargement des données…

Comment lire : les communes sont classées de la plus dotée à la moins dotée ; la valeur est écrite au bout de chaque barre. Les deux stations de l'Oisans dépassent nettement Grenoble.

Barres empilées

Chargement des données…

Comment lire : la hauteur totale donne les nuitées hôtelières de l'année ; la part du bas, les résidents en France ; la part du haut, les non-résidents. Le creux de 2020-2021 correspond à la crise sanitaire.

Format JSON :

JSONCode
{ "title": "Nuitées hôtelières en Isère par an", "labels": ["2023", "2024", "2025"], "series": [ { "name": "Résidents en France", "values": [1801610, 1749530, 1766500] }, { "name": "Non-résidents", "values": [527820, 550300, 636530] } ], "orientation": "vertical", "stacked": true, "yLabel": "Nuitées", "unit": "nuitées", "source": "Hébergements/Atout France - Données de fréquentation hébergements collectifs - INSEE.xlsx" }
  • orientation : "vertical" (par défaut) ou "horizontal" (conseillé pour des libellés longs ou plus de 12 catégories).
  • stacked: true empile les séries ; le total s'affiche dans l'info-bulle et le tableau.
  • Les valeurs négatives sont acceptées (la barre descend sous zéro).
  • Une seule série : une seule couleur, pas de légende (le titre dit ce qui est compté). Ne colorez jamais les barres selon leur valeur.
ReactCode
<BarChart src="/dataviz/ma-page/classement.json" /> <BarChart src="/dataviz/ma-page/par-jour.json" height={220} />

Heatmap : carte de chaleur

Échelle séquentielle

Chargement des données…

Comment lire : une ligne par année, une colonne par mois ; plus la case est foncée (plus claire en mode sombre), plus il y a de nuitées. Deux saisons ressortent : l'hiver (décembre à février) et l'été (juillet-août).

Échelle divergente

Chargement des données…

Comment lire : le gris veut dire « proche de la moyenne », le rouge « au-dessus », le bleu « au-dessous ». Plus la couleur est soutenue, plus l'écart est grand. L'écart est calculé par le portail (déduit).

Format JSON :

JSONCode
{ "title": "Nuitées touristiques en Isère, par mois", "rows": ["2022", "2023", "2024"], "cols": ["janv.", "févr.", "mars"], "values": [ [1160000, 1996000, 1373000], [1173000, 1967000, null], [1369000, 1931000, 1560000] ], "unit": "nuitées", "scale": "sequential", "source": "Hébergements/Nuitées Touristiques par mois éch départ - Flux Vision.xlsx" }
  • values : un tableau par ligne, une valeur par colonne ; null donne une case « Sans donnée ».
  • scale : "sequential" (une teinte, 5 classes calculées par quantiles) ou "diverging" (bleu, gris, rouge, 7 classes symétriques).
  • Options : midpoint (point milieu de l'échelle divergente, 0 par défaut, par exemple 100 pour un indice), breaks (seuils imposés : 4 seuils en séquentiel, 3 écarts positifs en divergent), legendTitle.
ReactCode
<Heatmap src="/dataviz/ma-page/jour-heure.json" />

ScatterPlot : nuage de points

Chargement des données…

Comment lire : chaque point est une commune ; plus il est à droite, plus elle a de lits touristiques ; plus il est haut, plus elle accueille de manifestations. La taille du point suit le nombre de sites recensés. Les axes sont logarithmiques : chaque graduation multiplie par 10.

Format JSON :

JSONCode
{ "title": "Hébergement et animation des communes de l'Isère", "xLabel": "Lits touristiques", "yLabel": "Manifestations Apidae", "xScale": "log", "yScale": "log", "sizeLabel": "Sites recensés", "annotate": ["Huez", "Grenoble"], "points": [ { "x": 4950, "y": 2, "label": "Huez", "group": "Aucun site surfréquenté signalé", "size": 35 }, { "x": 2377, "y": 935, "label": "Grenoble", "group": "Aucun site surfréquenté signalé", "size": 156 } ], "source": "Catalogue des sites du portail (scripts/build_sites_catalog.py)" }
  • group : 3 groupes colorés au plus, dans l'ordre d'apparition ; les suivants passent en « Autres ».
  • size : l'aire du point est proportionnelle à la valeur (rayon de 3 à 12 px).
  • annotate : libellés à écrire sur le graphique ; gardez-en 5 au plus, le reste se lit au survol.
  • xScale / yScale : "linear" (par défaut) ou "log" ; en logarithmique, les valeurs nulles ou négatives sont exclues du dessin (elles restent dans le tableau).
  • Options : xUnit, yUnit (unité affichée dans l'info-bulle).
ReactCode
<ScatterPlot src="/dataviz/ma-page/relation.json" height={360} />

ChoroplethMap : carte par commune

Chargement des données…

Comment lire : plus la commune est foncée (plus claire en mode sombre), plus elle compte de sites touristiques ; le gris clair signale une commune sans site recensé. Les communes entourées et nommées sont mises en avant par l'auteur.

Format JSON :

JSONCode
{ "title": "Sites touristiques recensés par commune du Grésivaudan", "base": "/dataviz/base/communes.json", "values": { "38567": 55, "38163": 24, "38006": 20, "38045": 3, "38062": null }, "unit": "sites", "legendTitle": "Sites recensés", "scale": "sequential", "highlight": ["38567", "38002"], "source": "Catalogue des sites du portail" }
  • values : une valeur par code INSEE de commune (chaîne de 5 caractères, "38185"). Une commune du fond absente de values est « Sans donnée ».
  • base : le fond de carte. Par défaut, /dataviz/base/communes.json (toutes les communes de l'Isère). La démo utilise un fond réduit au Grésivaudan : /dataviz/demo/communes-gresivaudan.json.
  • highlight : codes INSEE à entourer et à nommer (3 au plus conseillé).
  • scale, midpoint, breaks : comme pour Heatmap. Rapportez les valeurs à la population ou à la surface quand c'est pertinent : une grande commune a mécaniquement plus de tout.
  • Format d'un fond de carte : { "viewBox": "0 0 L H", "features": [{ "insee", "nom", "d", "cx", "cy" }] }, où d est le tracé SVG de la commune et cx, cy un point intérieur (pour les étiquettes).
ReactCode
<ChoroplethMap src="/dataviz/ma-page/par-commune.json" /> <ChoroplethMap src="/dataviz/ma-page/par-commune.json" base="/dataviz/base/communes.json" maxHeight={480} />

PointMap : carte de points

Chargement des données…

Comment lire : chaque point est un site touristique dont les données sont riches (score d'au moins 7 sur 10), coloré selon sa catégorie. Les sites d'autres catégories sont en gris. Le trait est une liaison d'exemple, pas un trajet réel.

Format JSON :

JSONCode
{ "title": "Sites touristiques bien documentés du Grésivaudan", "base": "/dataviz/demo/communes-gresivaudan.json", "points": [ { "x": 157.3, "y": 772.0, "label": "Itinéraire / exposition pédagogique (Chamrousse)", "group": "Nature et paysages" }, { "x": 158.1, "y": 445.6, "label": "Site d'exemple à Crolles", "group": "Patrimoine et culture", "href": "/sites/nom-du-site", "size": 12 } ], "lines": [{ "x1": 158.1, "y1": 445.6, "x2": 181.1, "y2": 786.1, "label": "Liaison d'exemple" }], "sizeLabel": "Passages par jour", "source": "Catalogue des sites du portail" }
  • x, y : coordonnées déjà projetées dans le repère du fond de carte (pas des latitudes et longitudes). Le fond indique sa projection ; le script qui produit le JSON fait la conversion (Lambert 93, puis la même mise à l'échelle que le fond).
  • href : un clic (ou Entrée au clavier) ouvre la page indiquée ; le lien figure aussi dans le tableau.
  • group : 3 groupes colorés au plus ; size : aire proportionnelle (rayon de 3 à 10 px).
  • lines : segments simples (liaisons, trajets schématiques), avec un libellé facultatif.
ReactCode
<PointMap src="/dataviz/ma-page/lieux.json" />

Gabarit d'une page DataViz

Copiez ce squelette dans 09-dataviz/NN-ma-page.mdx (NN fixe l'ordre dans le menu ; l'adresse sera /dataviz/ma-page).

ReactCode
--- title: "Titre complet de la page" sidebar_label: "Titre court" sidebar_icon: "chart-line" description: "Une phrase : la question à laquelle la page répond." --- :::info{title="En bref"} - **Pour qui** : … - **Ce que vous trouverez** : … - **Données utilisées** : fichiers du bucket, cités sous chaque graphique. - **Mise à jour** : JJ/MM/AAAA. ::: <KpiRow src="/dataviz/ma-page/kpi.json" /> ## Première question <LineChart src="/dataviz/ma-page/evolution.json" /> Comment lire : une phrase qui dit quoi regarder en premier. ## Limites - Ce que les données ne disent pas, les biais connus, les périodes manquantes.

Limites

  • Rendu au pré-rendu : un graphique chargé par src apparaît après le chargement de la page ; dans le HTML statique (moteur de recherche, impression sans JavaScript), seul son cadre est présent. Pour un graphique indispensable, passez les valeurs avec data.
  • Cartes : les fonds de carte sont simplifiés (tracés allégés à environ 60 m) ; ils ne conviennent pas pour mesurer des distances ou des surfaces.
  • Classes de couleur : les classes séquentielles sont calculées par quantiles ; deux cartes différentes n'ont donc pas les mêmes seuils. Pour comparer deux cartes, imposez les mêmes breaks.
  • Nombre de séries : 8 couleurs au plus pour les courbes et les barres, 3 groupes pour les nuages et les cartes ; au-delà, regroupez ou faites plusieurs graphiques.
  • Démos : les chiffres des démos sont réels mais servent d'exemple ; les analyses de référence sont dans l'onglet Analyses.