Carte choroplèthe
Géographie
Le premier graphique géo de la bibliothèque : colorer une carte du monde ou d'une région selon une valeur. Les données continues (valeur d'export, un indice, une part) pilotent une échelle de couleurs à seuils ; les données catégorielles (une catégorie « dernière année disponible », un statut) pilotent une carte explicite étiquette → couleur. La géographie est toujours une prop - ce package n'embarque aucune donnée topologique ; vous importez votre propre GeoJSON monde/région et le transmettez tel quel.
Mode catégoriel - colorsMapping l'emporte sur colorScale (le cas d'usage sdg-trade Data Availability : quelques catégories fixes étiquette → couleur, pas un dégradé numérique) :
Géographie de démonstration uniquement - et les frontières sont politiques
L'atlas mondial de cette page est un fichier GeoJSON simplifié du domaine public, fourni avec les exemples de la documentation à titre d'illustration. Il peut être faux : frontières, noms et tracés ne font PAS autorité, et certains sont contestés. Les frontières et noms « corrects » varient selon le public, la juridiction et l'organisation, et une carte qui se trompe est un problème politique, pas cosmétique. Rien de ce qui est rendu ici ne constitue une reconnaissance d'une frontière. Avant tout usage en production, vérifiez les frontières et la toponymie de votre propre fichier geography selon la politique cartographique de votre organisation : la bibliothèque rend le fichier tel quel, sans correction.
Le graphique ci-dessus est le même moteur dans chaque framework - seul le code d'intégration ci-dessous diffère.
Apportez votre propre géographie
geography accepte soit une FeatureCollection GeoJSON complète, soit un GeoFeatureItem[] pré-normalisé ({ id, geometry, name? }). Rien concernant les formes n'est embarqué dans @michi-vz/core - importez une carte du monde une fois dans votre application et réutilisez-la sur chaque carte choroplèthe :
import worldJson from "./world.json"; // votre propre FeatureCollection GeoJSON
import { ChoroplethMapChart } from "@michi-vz/react";
<ChoroplethMapChart
geography={worldJson}
dataSet={[
{ id: "USA", label: "United States", value: 2450 },
{ id: "DEU", label: "Germany", value: 1870 },
// ...
]}
colorScale={{ domain: [500, 1000, 2000], range: ["#eaf3fb", "#5b9bd5", "#123a63"] }}
/>L'id de chaque feature d'une FeatureCollection est lu depuis le Feature.id GeoJSON (repli sur properties.id) ; name depuis properties.name. Sources courantes : world-atlas (TopoJSON - convertissez avec feature() de topojson-client), Natural Earth, ou un fichier régional maintenu par votre équipe. Les docs/exemples de ce package n'embarquent qu'un petit échantillon illustratif de 12 formes - pas de vraies côtes - pour que la bibliothèque reste libre de toute dépendance à des données topologiques.
Schémas de couleurs nommés
colorScale.range attend des couleurs résolues. Pour une rampe nommée du clair au foncé, @michi-vz/core exporte sequentialScheme(name, count) : les schémas séquentiels monochromes de ColorBrewer, avec exactement les listes de couleurs que d3-scale-chromatic fournit sous schemePurples[k] et ses voisins, sans dépendance à d3.
import { sequentialScheme } from "@michi-vz/core";
const props = {
geography: worldJson,
dataSet,
// une échelle à seuils prend une couleur de plus que de seuils : 4 seuils, 5 couleurs
colorScale: { domain: [200, 500, 1000, 2000], range: sequentialScheme("purples", 5) },
};- Six noms :
"blues","greens","greys","oranges","purples"et"reds", aussi exportés sousSEQUENTIAL_SCHEME_NAMES(typeSequentialSchemeName). Un nom inconnu lève une erreur qui les liste. countva de 3 à 9 couleurs, du clair au foncé : un nombre plus petit renvoie 3 couleurs, un plus grand 9, et une valeur décimale est arrondie.- Chaque appel renvoie un nouveau tableau : vous pouvez l'inverser avec
.reverse()pour une rampe du foncé au clair sans toucher aux autres graphiques. - Les wrappers de framework installent
@michi-vz/corepour vous ; avec un gestionnaire de paquets strict comme pnpm, ajoutez-le à vos propres dépendances avant d'en importer quoi que ce soit. - Le
colorScaledeSymbolMapChartprend la même forme{ domain, range }, la fonction y sert donc aussi. - Couleurs issues de ColorBrewer 2.0 par Cynthia A. Brewer, Pennsylvania State University, sous licence Apache 2.0.
Faire defiler les annees
Donnez un date à chaque région et activez timeline : la carte devient un récit année par année, avec son propre bouton lecture et son curseur, une période colorée à la fois. Désactivé par défaut - sans opt-in, rien ne change.
Appuyez sur le bouton lecture sous le graphique : les données défilent année après année, un instantané à la fois. Faites glisser le curseur pour sauter à une année.
const ref = useRef<ChoroplethMapChartHandle>(null);
<ChoroplethMapChart ref={ref} {...props} timeline={{ speedMs: 1000, loop: true }} />;
// ref.current?.timeline() -> play() / pause() / seek(year) / seekIndex(i) / stepForward()<ChoroplethMapChart :options="{ ...props, timeline: { speedMs: 1000, loop: true } }" /><div use:choroplethMapChart={{ ...props, timeline: { speedMs: 1000, loop: true } }}></div>applyChoroplethMapChartProps(this.c.nativeElement, { ...props, timeline: { speedMs: 1000, loop: true } });<michi-vz-choropleth-map-chart id="c"></michi-vz-choropleth-map-chart>
<script>
const el = document.getElementById("c");
el.timeline = { speedMs: 1000, loop: true };
// el.getTimeline() -> play() / pause() / seek(year) / seekIndex(i)
</script>speedMsrègle le rythme,loopreboucle,autoplay: truedémarre au montage,showControl: falsemasque la barre intégrée.- Les valeurs glissent d'une période à l'autre par défaut (
interpolate) ; ajustez le mouvement avectweenMseteasing, ou passezinterpolate: falsepour des coupes nettes. Avec reduced motion, la coupe est toujours nette. - Le contrôleur headless reste disponible :
chart.timeline()exposeplay() / pause() / toggle() / seek(period) / seekIndex(i) / stepForward() / stepBack(), plusonStepetformatPerioddans la config pour une UI maison. seek(period)cherche d'abord la période, en comparant le texte :seek(2021)etseek("2021")vont tous les deux sur 2021, que vos dates soient des nombres ou des chaînes. Un nombre ne compte comme une position (0 = la première) que si aucune période ne correspond, et une chaîne qui ne correspond à rien ne fait rien.seekIndex(i)va toujours par position, comme le curseur intégré.- Les régions sans
daterestent visibles à chaque période.
Usage
import { ChoroplethMapChart } from "@michi-vz/react";
export default () => <ChoroplethMapChart {...props} />; // props = les options du graphique<script setup>
import { ChoroplethMapChart } from "@michi-vz/vue";
</script>
<template>
<ChoroplethMapChart :options="props" />
</template><script>
import { choroplethMapChart } from "@michi-vz/svelte";
</script>
<div use:choroplethMapChart={props}></div>// main.ts - enregistrer les éléments une fois
import "@michi-vz/angular";
import { applyChoroplethMapChartProps } from "@michi-vz/angular";
// composant (utilise CUSTOM_ELEMENTS_SCHEMA)
// template : <michi-vz-choropleth-map-chart #c></michi-vz-choropleth-map-chart>
applyChoroplethMapChartProps(this.c.nativeElement, props);<script type="module" src="https://cdn.jsdelivr.net/npm/@michi-vz/wc/dist/michi-vz-wc.bundle.js"></script>
<michi-vz-choropleth-map-chart id="c"></michi-vz-choropleth-map-chart>
<script>
Object.assign(document.getElementById("c"), props); // geography, dataSet, title, …
</script>import { mountChoroplethMapChart } from "@michi-vz/core";
const chart = mountChoroplethMapChart(el, props);
chart.update(next);
chart.getContext(); // agnostique du moteur de rendu, prêt pour un LLM
chart.destroy();API
Les props sont typées comme ChoroplethMapChartProps dans @michi-vz/core. Communes à tous les graphiques : width, height, margin, colors / colorsMapping, renderer ("svg", "canvas", ou expérimentalement "webgpu"), highlightItems, disabledItems, et les callbacks on*. onChartDataProcessed / getContext() renvoient le ChartContext agnostique du moteur de rendu.
Notes de comportement
Jointure de dataSet avec geography - joinBy
Chaque ligne de dataSet ({ id, label, value?, color? }) est mise en correspondance avec une feature de géographie via joinBy : "id" (par défaut) compare ChoroplethDataItem.id à GeoFeatureItem.id / Feature.id GeoJSON - la jointure propre et stable (p. ex. des codes ISO-A3). "name" compare label à GeoFeatureItem.name / properties.name à la place, pour des données indexées par nom de pays plutôt que par code. Une feature sans ligne correspondante (ou une ligne dans disabledItems) est peinte avec noDataColor et son infobulle reçoit la forme de repli { id, name } au lieu de la ligne complète.
Priorité de résolution des couleurs
colorsMapping[label] (catégoriel, explicite) l'emporte sur colorScale (continu - un range hexadécimal résolu + un domain numérique, construit dans un scaleThreshold d3 ; les valeurs hors domaine se calent sur la première/dernière couleur du range) qui l'emporte sur la color propre à la ligne qui l'emporte sur la palette auto-assignée colors. Le cœur reste libre de d3-scale-chromatic - passez des couleurs hexadécimales déjà résolues à colorScale.range, depuis le sequentialScheme du cœur ou depuis n'importe où ailleurs dans votre application.
Projections - les 13, un défaut
projection distribue vers geoEqualEarth, geoMercator, geoTransverseMercator, geoAlbers, geoAlbersUsa, geoAzimuthalEqualArea, geoAzimuthalEquidistant, geoOrthographic, geoConicConformal, geoConicEqualArea, geoConicEquidistant, geoRobinson (le défaut), et geoGilbert (les deux depuis d3-geo-projection). projectionConfig (scale, rotate, center, parallels) affine la projection choisie ; les champs omis reprennent les défauts du legacy sdg-trade MapChoropleth (rotate: [-18, 0], center: [0, 10], une échelle dérivée de la largeur) plutôt que projection.fitSize - cela reproduit exactement le résultat visuel de ce graphique plutôt que de recadrer sur un autre cadrage. geoAlbersUsa est une projection composite fixe : elle ignore rotate / center / parallels.
Rendu : SVG, canvas et un WebGPU délégué
renderer="svg" (par défaut) dessine un <path class="region"> par feature. renderer="canvas" dessine via geoPath(projection, ctx) - d3-geo effectue un rendu natif et efficace directement sur un contexte 2D canvas, donc rien ne reparse la chaîne de chemin SVG ni ne réimplémente les maths de projection. renderer="webgpu" délègue au même moteur canvas-2D plutôt que de trianguler des polygones arbitraires sur le GPU : les régions réelles sont fréquemment concaves, multi-anneaux, avec des trous (une enclave, un archipel), et une triangulation GPU correcte de polygones simples arbitraires nécessite un véritable ear-clipping - hors de proportion face au rendu 2D natif déjà rapide de d3-geo pour un graphique typiquement de quelques dizaines à quelques centaines de chemins. Il reste conditionné par les capacités (navigator.gpu) et rapporte le moteur effectif via getContext().renderer, comme tout autre graphique.
Survol / infobulle
tooltipFormatter(d) reçoit le ChoroplethDataItem complet pour une région appariée, ou { id, name } pour une région non appariée. En mode canvas/webgpu, le survol est résolu en reprojetant la géométrie brute de chaque feature et en exécutant un test point-dans-polygone (pas une approximation par boîte englobante), donc les frontières irrégulières sont correctement détectées. Le survol estompe toutes les autres régions (le comportement standard highlightItems de la maison) plutôt qu'une bordure :hover CSS persistante qui s'assombrit - l'effet de survol du graphique legacy.
Chargement / absence de données
isLoading et isNodata pilotent la superposition (React : isLoadingComponent / isNodataComponent), identique à tout autre graphique de la maison.
Autorités de couleur côté consommateur : le contexte porte
legendData({ label, color, dataLabelSafe }) pour qu'un système de couleur par injection CSS puisse indexer des règles par étiquette ;onChartDataProcessedn'est émis que lorsque le contexte change.
