Choroplethenkaart
Geografie
De eerste geo-grafiek van de bibliotheek: kleur een wereld- of regiokaart op basis van een waarde. Continue data (exportwaarde, een index, een aandeel) stuurt een drempel-kleurschaal aan; categorische data (een categorie "laatst beschikbare jaar", een status) stuurt een expliciete label → kleur-kaart aan. Geografie is altijd een prop - dit package bevat geen topologiegegevens; je importeert je eigen wereld-/regio-GeoJSON en geeft die rechtstreeks door.
Categorische modus - colorsMapping wint van colorScale (de sdg-trade Data Availability-use case: een handvol vaste label → kleur-categorieën, geen numeriek verloop):
Alleen demogeografie - en grenzen zijn politiek
De wereldatlas op deze pagina is een vereenvoudigd GeoJSON-bestand uit het publieke domein, meegeleverd met de documentatievoorbeelden ter illustratie. Hij kan fout zijn: grenzen, namen en vormen zijn NIET gezaghebbend, en sommige zijn omstreden. Welke grenzen en namen "juist" zijn verschilt per publiek, rechtsgebied en organisatie, en een kaart die het mis heeft is een politiek probleem, geen cosmetisch. Niets wat hier wordt getekend is een erkenning van een grens. Controleer vóór productiegebruik de grenzen en naamgeving van het geography-bestand dat je doorgeeft aan het cartografische beleid van je organisatie: de bibliotheek tekent het bestand zoals het is en corrigeert niets.
De grafiek hierboven gebruikt in elk framework dezelfde engine - alleen de integratiecode hieronder verschilt.
Breng je eigen geografie mee
geography accepteert ofwel een volledige GeoJSON-FeatureCollection, ofwel een vooraf genormaliseerde GeoFeatureItem[] ({ id, geometry, name? }). Niets aan de vormen wordt meegeleverd in @michi-vz/core - importeer één keer een wereldkaart in je app en hergebruik die op elke choroplethenkaart:
import worldJson from "./world.json"; // je eigen GeoJSON FeatureCollection
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"] }}
/>De id van elke feature in een FeatureCollection wordt gelezen uit de GeoJSON Feature.id (met terugval op properties.id); name uit properties.name. Populaire bronnen: world-atlas (TopoJSON - converteer met feature() van topojson-client), Natural Earth, of een regiobestand dat je eigen team onderhoudt. De docs/voorbeelden van dit package bevatten slechts een klein illustratief voorbeeld van 12 vormen - geen echte kustlijnen - zodat de bibliotheek vrij blijft van elke afhankelijkheid van topologiegegevens.
Kleurschema's op naam
colorScale.range verwacht opgeloste kleuren. Voor een benoemde reeks van licht naar donker exporteert @michi-vz/core sequentialScheme(name, count): de sequentiële eenkleurige schema's van ColorBrewer, met precies de kleurlijsten die d3-scale-chromatic levert als schemePurples[k] en verwanten, zonder d3-afhankelijkheid.
import { sequentialScheme } from "@michi-vz/core";
const props = {
geography: worldJson,
dataSet,
// een drempelschaal neemt één kleur meer dan drempels: 4 drempels, 5 kleuren
colorScale: { domain: [200, 500, 1000, 2000], range: sequentialScheme("purples", 5) },
};- Zes namen:
"blues","greens","greys","oranges","purples"en"reds", ook geëxporteerd alsSEQUENTIAL_SCHEME_NAMES(typeSequentialSchemeName). Een onbekende naam gooit een fout die ze opsomt. countloopt van 3 tot 9 kleuren, van licht naar donker: een kleiner aantal geeft 3 kleuren, een groter aantal 9, en een breuk wordt afgerond.- Elke aanroep geeft een nieuwe array terug, dus je kunt hem met
.reverse()omdraaien voor een reeks van donker naar licht zonder andere grafieken te raken. - De framework-wrappers installeren
@michi-vz/corevoor je; met een strikte package manager zoals pnpm voeg je het aan je eigen dependencies toe voordat je eruit importeert. - De
colorScalevanSymbolMapChartheeft dezelfde vorm{ domain, range }, dus de helper werkt daar ook. - Kleuren uit ColorBrewer 2.0 van Cynthia A. Brewer, Pennsylvania State University, onder de Apache License 2.0.
Speel door de jaren heen
Geef elke regio een date en zet timeline aan: de kaart wordt een verhaal per jaar, met een eigen afspeelknop en scrubber die telkens één periode inkleurt. Standaard uit - zonder opt-in verandert er niets.
Druk op de afspeelknop onder de grafiek: de data stapt door de jaren, één momentopname per keer. Sleep de scrubber om naar een jaar te springen.
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>speedMsbepaalt het tempo,loopbegint opnieuw,autoplay: truestart bij mounten,showControl: falseverbergt de ingebouwde balk.- Waarden glijden standaard tussen periodes (
interpolate); stem de beweging af mettweenMseneasing, of zetinterpolate: falsevoor harde overgangen. Met reduced motion is de overgang altijd hard. - De headless controller is altijd beschikbaar:
chart.timeline()biedtplay() / pause() / toggle() / seek(period) / seekIndex(i) / stepForward() / stepBack(), plusonStepenformatPeriodin de config voor eigen UI. seek(period)zoekt eerst de periode en vergelijkt als tekst, dusseek(2021)enseek("2021")komen allebei op 2021 uit, of je datums nu getallen of strings zijn. Een getal telt alleen als positie (0 = de eerste) als geen periode past, en een string die nergens bij past doet niets.seekIndex(i)gaat altijd op positie, net als de ingebouwde scrubber.- Regio's zonder
dateblijven in elke periode zichtbaar.
Gebruik
import { ChoroplethMapChart } from "@michi-vz/react";
export default () => <ChoroplethMapChart {...props} />; // props = the chart options<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 - registreer de elementen één keer
import "@michi-vz/angular";
import { applyChoroplethMapChartProps } from "@michi-vz/angular";
// component (gebruikt 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(); // renderer-onafhankelijk, LLM-ready
chart.destroy();API
Props zijn getypeerd als ChoroplethMapChartProps in @michi-vz/core. Gedeeld door alle grafieken: width, height, margin, colors / colorsMapping, renderer ("svg", "canvas", of experimenteel "webgpu"), highlightItems, disabledItems en de on*-callbacks. onChartDataProcessed / getContext() geven de renderer-onafhankelijke ChartContext terug.
Gedragsnotities
dataSet koppelen aan geography - joinBy
Elke dataSet-rij ({ id, label, value?, color? }) wordt gekoppeld aan een geografie-feature via joinBy: "id" (standaard) matcht ChoroplethDataItem.id met GeoFeatureItem.id / GeoJSON Feature.id - de schone, stabiele koppeling (bijv. ISO-A3-codes). "name" matcht in plaats daarvan label met GeoFeatureItem.name / properties.name, voor data die op landnaam in plaats van code is geïndexeerd. Een feature zonder overeenkomende rij (of een rij in disabledItems) wordt getekend met noDataColor en de tooltip ontvangt de terugvalvorm { id, name } in plaats van de volledige rij.
Prioriteit van kleurresolutie
colorsMapping[label] (categorisch, expliciet) wint van colorScale (continu - een opgeloste hex-range + numeriek domain, gebouwd in een d3-scaleThreshold; waarden buiten het domein klemmen aan de eerste/laatste kleur van de range) die wint van de eigen color van de rij die wint van het automatisch toegewezen colors-palet. De kern blijft vrij van d3-scale-chromatic - geef al opgeloste hexkleuren door aan colorScale.range, uit de eigen sequentialScheme van de kern of van waar dan ook in je app.
Projecties - alle 13, één standaard
projection verdeelt naar geoEqualEarth, geoMercator, geoTransverseMercator, geoAlbers, geoAlbersUsa, geoAzimuthalEqualArea, geoAzimuthalEquidistant, geoOrthographic, geoConicConformal, geoConicEqualArea, geoConicEquidistant, geoRobinson (de standaard), en geoGilbert (beide uit d3-geo-projection). projectionConfig (scale, rotate, center, parallels) verfijnt de gekozen projectie; weggelaten velden vallen terug op de eigen standaarden van de legacy sdg-trade MapChoropleth-grafiek (rotate: [-18, 0], center: [0, 10], een breedte-afgeleide basisschaal) in plaats van projection.fitSize - dit reproduceert exact het visuele resultaat van die grafiek in plaats van opnieuw te passen op een ander kader. geoAlbersUsa is een vaste samengestelde projectie: ze negeert rotate / center / parallels.
Rendering: SVG, canvas en een gedelegeerde WebGPU
renderer="svg" (standaard) tekent één <path class="region"> per feature. renderer="canvas" tekent via geoPath(projection, ctx) - d3-geo rendert nativeif en efficiënt rechtstreeks naar een 2D-canvascontext, dus niets herparseert de SVG-padstring of herimplementeert de projectiewiskunde. renderer="webgpu" delegeert naar dezelfde canvas-2D-renderer in plaats van willekeurige polygonen op de GPU te trianguleren: reële regio's zijn vaak concaaf, meerdere ringen, met gaten (een enclave, een eilandengroep), en correcte GPU-triangulatie van willekeurige eenvoudige polygonen vereist echte ear-clipping - buiten proportie ten opzichte van de al snelle native 2D-rendering van d3-geo voor een grafiek met doorgaans enkele tientallen tot enkele honderden paden. Het blijft capability-gated op navigator.gpu en rapporteert de effectieve renderer via getContext().renderer, net als elke andere grafiek.
Hover / tooltip
tooltipFormatter(d) ontvangt het volledige ChoroplethDataItem voor een gekoppelde regio, of { id, name } voor een niet-gekoppelde. In canvas-/webgpu-modus wordt hoveren opgelost door de ruwe geometrie van elke feature opnieuw te projecteren en een punt-in-polygoon-test uit te voeren (geen bounding-box-benadering), zodat onregelmatige grenzen correct worden gedetecteerd. Hoveren dimt elke andere regio (het standaard highlightItems-gedrag van het huis) in plaats van een blijvende CSS-:hover-randverdonkering - het hover-effect van de legacy-grafiek.
Laden / geen data
isLoading en isNodata sturen de overlay aan (React: isLoadingComponent / isNodataComponent), identiek aan elke andere grafiek in het huis.
Kleurautoriteit van de consument: de context bevat
legendData({ label, color, dataLabelSafe }) zodat een CSS-injectie-kleursysteem regels per label kan koppelen;onChartDataProcessedwordt alleen uitgezonden wanneer de context verandert.
