Conteneur de carte interactive basé sur Leaflet, avec fonds de carte souverains (IGN Géoplateforme). Il gère l'initialisation, le fond de tuiles, le viewport et l'accessibilité — les données sont projetées par des composants compagnons.

Famille de 5 composants : dsfr-data-map est le conteneur. Les données sont projetées par des dsfr-data-map-layer enfants (une couche = une source), l'affichage au clic est défini par dsfr-data-map-popup, les vignettes territoriales (DROM, Corse) par dsfr-data-map-inset et l'animation temporelle par dsfr-data-map-timeline.

Vue d'ensemble de la famille cartographique

Pipeline

dsfr-data-source (A) ──┐
                       ├──> dsfr-data-map                      (conteneur : Leaflet, tuiles, viewport, a11y)
dsfr-data-source (B) ──┘     ├── dsfr-data-map-layer source="A"  (geoshape choroplèthe)
                             ├── dsfr-data-map-layer source="B"  (markers, cercles, heatmap...)
                             ├── dsfr-data-map-popup             (popup / modale / volet au clic)
                             ├── dsfr-data-map-inset             (encarts DROM, Corse...)
                             └── dsfr-data-map-timeline          (lecture temporelle des couches à time-field)

Chaque couche est connectée à sa propre source : le multi-source est naturel (ex. contours de régions + POI pharmacies sur la même carte). Les couches participent au data-bridge comme n'importe quel composant d'affichage (abonnement par source, commandes dsfr-data-source-command pour le bbox).

Bundle et chargement

Accessibilité intégrée

Le compagnon dsfr-data-a11y détecte les cartes et adapte ses libellés (« Données de la carte »).

Attributs

AttributTypeDéfautDescription
centerString46.603,2.888Centre initial de la carte, au format "lat,lon".
zoomNumber6Niveau de zoom initial (1-18).
min-zoomNumber2Zoom minimum autorise.
max-zoomNumber18Zoom maximum autorise.
heightString500pxHauteur CSS (px, vh, rem). Un % est un ratio de la LARGEUR (ex: "60%" = 60 % de la largeur).
tilesStringign-planFond de carte : ign-plan, ign-ortho, ign-cadastre, osm-fr (alias osm), osm-standard, opentopomap, ou une URL template. Presets deprecies (redirigent vers ign-plan avec un warning) : ign-topo, carto-positron, carto-dark.
tiles-attributionString""Mention d'attribution affichée sur la carte quand tiles est une URL custom (obligatoire pour respecter l'ODbL et les CGU du fournisseur). Ignoré sur un preset connu, qui porte déjà son attribution. Accepte du HTML (liens).
tiles-style"" · muted · grey""Atténuation du fond de carte pour les cartes thématiques : muted (gris + 55 % d'opacité), grey (niveaux de gris). Vide (défaut) : fond tel quel. Filtre CSS sur le volet des tuiles de cette carte seulement ; les encarts héritent du réglage. Un fond « neutre » = ign-plan + tiles-style="muted" (#686).
sovereign-onlyBooleanfalseRestreint tiles aux presets IGN souverains : tout autre preset ou URL custom est refuse (console.warn) et remplace par ign-plan.
no-controlsBooleanfalseMasque les controles de zoom.
lockedBooleanfalseCarte verrouillee : aucune interaction (pan/zoom/clavier) — encarts, vignettes
insetsString""Raccourci encarts territoriaux : groupe ("drom") et/ou territoires nommés séparés par des virgules ("drom,corse", "guadeloupe,saint-pierre-et-miquelon")
fit-boundsBooleanfalseAjuste le viewport aux données à chaque mise à jour. Combiné à max-bounds, l'emprise est clippée à la zone : les DROM ne dézooment pas la vue, un filtre régional zoome dessus.
max-boundsString""Limites du déplacement, au format "latSW,lonSW,latNE,lonNE". Clippe aussi le fit de fit-bounds quand fit-zone est vide.
fit-zoneString""Zone sur laquelle fit-bounds est clippé, au format "latSW,lonSW,latNE,lonNE" — le pan reste libre. Défaut : max-bounds s'il est renseigné ; sinon la métropole (41,-5.5,51.5,10) dès que la carte porte un encart ultramarin (insets="drom"…), pour que les DROM ne dézooment pas la vue ; sinon aucune zone. fit-zone="none" désactive le clip (#687).
fit-max-zoomNumber0Zoom maximal atteint par fit-bounds (ex. 12) : évite le zoom 18 sur un point isolé quand les données se réduisent à un marqueur. 0 (défaut) = pas de plafond, max-zoom s'applique.
nameString""Titre de la carte, utilise comme nom accessible (aria-label).

Fonds de carte prédéfinis

Tuiles accessibles sans clé API. Les presets ign-* sont servis par la Géoplateforme nationale IGN (infrastructure cartographique de l'État, hébergée en France). Le preset osm-fr est servi par l'association OpenStreetMap France (association loi 1901, infra hébergée en France, distincte de l'OSM Foundation).

Les fonds non-IGN sont fournis en best effort par des associations : aucune garantie de disponibilité, et des conditions d'usage propres à chaque fournisseur. En particulier, la politique d'usage d'OSM France exige un site public, sans login ni intranet, sans but lucratif et à trafic modéré — ce qui exclut osm-fr d'un déploiement derrière authentification. Détail dans docs/THIRD-PARTY-LICENSES.md.

PresetSourceSouverainEndpoint
ign-planGéoplateforme IGN — Plan IGNOuidata.geopf.fr/wmts (layer GEOGRAPHICALGRIDSYSTEMS.PLANIGNV2)
ign-orthoGéoplateforme IGN — OrthophotoOuidata.geopf.fr/wmts (layer ORTHOIMAGERY.ORTHOPHOTOS)
ign-cadastreGéoplateforme IGN — CadastreOuidata.geopf.fr/wmts (layer CADASTRALPARCELS.PARCELLAIRE_EXPRESS)
osm-frOpenStreetMap France (association)Non (associatif hors État){s}.tile.openstreetmap.fr/osmfr
osm-standardOpenStreetMap (OSM Foundation)Nontile.openstreetmap.org
opentopomapOpenTopoMap (CC-BY-SA)Non{s}.tile.opentopomap.org

Alias et dépréciation : tiles="osm" reste accepté et pointe vers le preset osm-fr. Trois presets sont dépréciés et résolvent vers ign-plan avec un console.warn : ign-topo (#429 — couche BDUNI quasi vide, couches SCAN topo soumises à clé API), carto-positron et carto-dark (#576 — CARTO exige désormais une clé API et filigrane les tuiles anonymes, en HTTP 200 donc sans erreur détectable ; la clé est nominative et le service raster est en cours de retrait). Toute autre valeur est traitée comme une URL template custom {z}/{x}/{y}, qui exige alors tiles-attribution.

Mode sovereign-only : pour les DSI qui imposent une politique « zéro tiers externe non souverain », l'attribut booléen sovereign-only restreint les presets disponibles aux seules tuiles IGN. Tout autre preset ou URL custom est refusé avec un avertissement console et remplacé par ign-plan.

Laisser le lecteur choisir son fond

tiles décide du fond une fois pour toutes. Sur une carte de terrain, le lecteur a souvent besoin des deux : le plan pour se repérer, l'orthophoto pour reconnaître les lieux. tiles-switcher énumère les fonds qu'on lui propose et rend un menu déroulant étiqueté « Fond de carte » en haut à droite, utilisable au clavier.

AttributTypeDéfautDescription
tiles-switcherString""Fonds proposés au LECTEUR, séparés par des virgules (ex. "ign-plan,ign-ortho"). Vide (défaut) : aucun sélecteur, seul tiles décide. Rend un menu déroulant étiqueté « Fond de carte » en haut à droite de la carte, utilisable au clavier ; changer de fond met à jour la carte et ses encarts. Les entrées hors presets connus sont écartées avec un avertissement, et il en faut au moins deux pour que le sélecteur apparaisse. Sans effet avec locked ou no-controls (#744).
<dsfr-data-map
  center="48.85,2.35" zoom="12"
  tiles="ign-plan"
  tiles-switcher="ign-plan,ign-ortho,ign-cadastre">
  <dsfr-data-map-layer source="poi"></dsfr-data-map-layer>
</dsfr-data-map>

Les entrées hors presets connus sont écartées avec un avertissement, et il en faut au moins deux pour que le sélecteur apparaisse. Changer de fond met à jour la carte et ses encarts. Sans effet avec locked ou no-controls, qui retirent précisément l'interaction (#744). sovereign-only continue de s'appliquer : un fond non souverain proposé au lecteur est écarté comme il le serait sur tiles.

Plein écran

Une carte dense se lit mal dans une colonne de page. fullscreen ajoute, à droite des boutons de zoom, un bouton « Plein écran » : la carte, avec ses couches, sa légende, ses encarts et son sélecteur de fond, occupe tout l'écran, et en revient par le même bouton ou la touche Échap.

AttributTypeDéfautDescription
fullscreenBooleanfalseBouton de plein écran (#780), posé à droite des boutons de zoom : la carte (couches, légende, encarts et sélecteur de fond compris) occupe tout l'écran, et en revient par le même bouton ou la touche Échap. Utilisable au clavier, état porté par aria-pressed et par le libellé, et annoncé. Absent si le navigateur n'offre pas le plein écran d'un élément (Safari sur iPhone), et sans effet avec locked ou no-controls.
<dsfr-data-map center="46.6,2.5" zoom="6" fullscreen name="Bornes de recharge">
  <dsfr-data-map-layer source="bornes" type="marker" cluster></dsfr-data-map-layer>
</dsfr-data-map>

C'est un vrai bouton, atteint au clavier avant la carte. Son état passe par aria-pressed et par son libellé (« Plein écran », « Quitter le plein écran »), et chaque bascule est annoncée aux lecteurs d'écran. La page est notifiée par l'événement dsfr-data-map-fullscreen-change (detail.fullscreen). Le bouton n'apparaît pas quand le navigateur ne sait pas mettre un élément en plein écran (Safari sur iPhone), ni avec locked ou no-controls. La capture d'image de la carte reste hors périmètre : tuiles d'origines croisées et légende hors du canevas.

Événements

Le conteneur n'émet pas d'événement custom. Les couches enfantes participent au data-bridge (abonnement à leur source, commandes bbox) et dsfr-data-map-layer émet dsfr-data-map-layer-time-ready quand un découpage temporel est prêt.

API JavaScript

MéthodeDescription
getLeafletMap()Retourne l'instance L.Map (ou null avant init)
getLeafletLib()Retourne le module Leaflet chargé dynamiquement
registerLayerBounds(key, bounds)Déclare les bounds d'une couche pour le fit-bounds (les bounds d'une clé sont remplacés à chaque rendu)
unregisterLayerBounds(key)Retire une couche du calcul de fit
announceToScreenReader(msg)Annonce un message dans la live region assertive
updateDescription(summaries)Met à jour la description sr-only de la carte (appelé par les couches)

Exemples

1. Carte simple avec une couche de POI

<dsfr-data-source id="bornes" api-type="opendatasoft"
  base-url="https://odre.opendatasoft.com" dataset-id="bornes-irve"
  select="geo_point_2d,nom_station,puissance_nominale,adresse"
  limit="5000">
</dsfr-data-source>

<dsfr-data-map name="Bornes de recharge en France" center="46.6,2.3" zoom="6" tiles="ign-plan" fit-bounds>
  <dsfr-data-map-layer source="bornes" type="marker"
    geo-field="geo_point_2d"
    tooltip-field="nom_station"
    cluster>
  </dsfr-data-map-layer>
</dsfr-data-map>

2. Hauteur en ratio + carte verrouillée (vignette)

<!-- height="60%" = hauteur à 60 % de la largeur courante (aspect-ratio responsive) -->
<dsfr-data-map center="48.85,2.35" zoom="11" height="60%"
  locked no-controls tiles="ign-plan" name="Vignette Paris">
  <dsfr-data-map-layer source="arrondissements" type="geoshape"
    geo-field="geo_shape" no-interactive color="#000091" fill-opacity="0.1">
  </dsfr-data-map-layer>
</dsfr-data-map>

3. Fit clippé (métropole + DROM, ADR-094)

fit-bounds ajuste la vue aux données, mais les territoires d'outre-mer feraient dézoomer sur l'Atlantique. max-bounds clippe le fit sur la métropole ; les DROM restent visibles dans les encarts.

<dsfr-data-map center="46.5,2.6" zoom="6" min-zoom="3" height="620px"
  tiles="ign-plan" fit-bounds max-bounds="38.5,-13,54,15"
  insets="drom" name="Territoires engagés">
  <dsfr-data-map-layer source="territoires" type="geoshape"
    geo-field="geojson" fill-field="habitants"
    selected-palette="sequentialAscending" tooltip-field="nom">
  </dsfr-data-map-layer>
  <dsfr-data-map-popup mode="panel-right" title-field="nom">
    <template><p>{{habitants:number}} habitants</p></template>
  </dsfr-data-map-popup>
</dsfr-data-map>

Légende — dsfr-data-map-legend

Compagnon déclaratif placé dans la carte : il rend la légende des couches (classes d'une choroplèthe, paires de color-map, ou entrée unique d'une couche monochrome) et se met à jour avec elles.

AttributTypeDéfautDescription
forString""Id (ou source) de la couche dsfr-data-map-layer décrite. Vide = toutes les couches directes de la carte hôte, entrées concaténées.
labelString""Titre de la légende, affiché au-dessus de la liste (ex. « Densité (hab./km²) »). Sert aussi de libellé à l'entrée unique d'une couche monochrome.

Composants compagnons