Verticale gestapelde staven
Samenstelling
"Waaruit bestaat elke categorie, en hoe verschuift de mix ertussen?" Stapel de onderdelen in één staaf per categorie en de samenstelling leest in één oogopslag. Wanneer een segment ontbreekt, markeert een expliciete bescherming het hiaat in plaats van het stilzwijgend plat te slaan naar nul.
Moet je twee dingen naast elkaar vergelijken? Geef meer dan één reeks door in dataSet en de staven groeperen: per x-categorie krijg je één gestapelde staaf per reeks, samen geclusterd. Hier, twee regio's over drie jaar, elke staaf opgesplitst in vijf productlijnen - zodat je in één keer leest welke regio groter is en hoe de mix verschilt:
De grafiek hierboven is dezelfde engine in elk framework - alleen de integratiecode hieronder verschilt.
Veel data op WebGPU Experimenteel
VerticalStackBarChart heeft een optionele renderer="webgpu" die de staven op de GPU tekent, terwijl assen, labels en tooltips op de SVG-laag blijven. Dit is capability-gated: in een browser zonder WebGPU wordt automatisch teruggevallen op canvas, en getContext().renderer rapporteert wat daadwerkelijk is getekend.
Onthulanimatie
De grafiek tekent zichzelf van links naar rechts bij het mounten, waarbij de elementen na elkaar verschijnen voordat ze op hun plek vallen. Standaard uit - een grafiek kiest ervoor met de progressiveDraw-prop.
Elke lijn groeit van het eerste naar het laatste jaar; het label volgt de punt en komt tot stilstand bij het lijneinde. Met reduced motion ingeschakeld verschijnt de grafiek meteen volledig getekend.
progressiveDraw: true gebruikt de standaardinstellingen (1200 ms, easeInOutCubic). Een configuratieobject verfijnt het gedrag:
const ref = useRef<VerticalStackBarChartHandle>(null);
<VerticalStackBarChart
ref={ref}
{...props}
progressiveDraw={{ durationMs: 2000 }}
/>;
// ref.current?.replay() speelt de animatie opnieuw af<VerticalStackBarChart :options="{ ...props, progressiveDraw: { durationMs: 2000 } }" /><div use:verticalStackBarChart={{ ...props, progressiveDraw: { durationMs: 2000 } }}></div>applyVerticalStackBarChartProps(this.c.nativeElement, {
...props,
progressiveDraw: { durationMs: 2000 },
});<michi-vz-vertical-stack-bar-chart id="c"></michi-vz-vertical-stack-bar-chart>
<script>
const el = document.getElementById("c");
el.progressiveDraw = { durationMs: 2000 };
// el.replay() speelt de animatie opnieuw af
</script>durationMseneasing("linear", "easeOutQuad", "easeInOutCubic", of een eigen(t) => t-functie) bepalen het tempo.autoplay: falserendert de grafiek volledig getekend; roepreplay()aan (React-ref-handle, webcomponent-methode of de core-instantie) om de animatie op aanvraag te starten.replayOnUpdate: trueherhaalt de animatie bij elke datawijziging.- Respecteert
prefers-reduced-motion: de grafiek verschijnt dan meteen volledig getekend.
Speel door de jaren heen
De data beslaat al meerdere jaren, dus er is niets te taggen. Zet timeline aan: de eigen afspeelknop en scrubber van de grafiek stappen door die jaren - bij elke stap tekent elke gestapelde staaf zich alleen tot het actieve jaar, en tijdens het afspelen loopt de stapel vloeiend verder door. Scrub je terug, dan trekken de staven zich weer terug. Hoveren toont alleen wat al echt getekend is. Standaard uit - zonder opt-in verandert er niets.
Druk op de afspeelknop onder de grafiek: de grafiek tekent zich verder door tot elk jaar terwijl hij speelt. Sleep de scrubber om naar een jaar te springen.
const ref = useRef<VerticalStackBarChartHandle>(null);
<VerticalStackBarChart ref={ref} {...props} timeline={{ speedMs: 1000, loop: true }} />;
// ref.current?.timeline() -> play() / pause() / seek(year) / stepForward()<VerticalStackBarChart :options="{ ...props, timeline: { speedMs: 1000, loop: true } }" /><div use:verticalStackBarChart={{ ...props, timeline: { speedMs: 1000, loop: true } }}></div>applyVerticalStackBarChartProps(this.c.nativeElement, { ...props, timeline: { speedMs: 1000, loop: true } });<michi-vz-vertical-stack-bar-chart id="c"></michi-vz-vertical-stack-bar-chart>
<script>
const el = document.getElementById("c");
el.timeline = { speedMs: 1000, loop: true };
// el.getTimeline() -> play() / pause() / seek(year)
</script>speedMsbepaalt het tempo,loopbegint opnieuw,autoplay: truestart bij mounten,showControl: falseverbergt de ingebouwde balk.- De headless controller is altijd beschikbaar:
chart.timeline()biedtplay() / pause() / toggle() / seek(period) / stepForward() / stepBack(), plusonStepenformatPeriodin de config voor eigen UI. - Waarden glijden standaard tussen jaren (
interpolate); zetinterpolate: falsevoor harde overgangen. Met reduced motion is de overgang altijd hard. timelinewint het vanprogressiveDrawwanneer beide op dezelfde grafiek staan.
Gebruik
import { VerticalStackBarChart } from "@michi-vz/react";
export default () => <VerticalStackBarChart {...props} />; // props = the chart options<script setup>
import { VerticalStackBarChart } from "@michi-vz/vue";
</script>
<template>
<VerticalStackBarChart :options="props" />
</template><script>
import { verticalStackBarChart } from "@michi-vz/svelte";
</script>
<div use:verticalStackBarChart={props}></div>// main.ts - register the elements once
import "@michi-vz/angular";
import { applyVerticalStackBarChartProps } from "@michi-vz/angular";
// component (uses CUSTOM_ELEMENTS_SCHEMA)
// template: <michi-vz-vertical-stack-bar-chart #c></michi-vz-vertical-stack-bar-chart>
applyVerticalStackBarChartProps(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-vertical-stack-bar-chart id="c"></michi-vz-vertical-stack-bar-chart>
<script>
Object.assign(document.getElementById("c"), props); // dataSet/series, title, …
</script>import { mountVerticalStackBarChart } from "@michi-vz/core";
const chart = mountVerticalStackBarChart(el, props);
chart.update(next);
chart.getContext(); // renderer-agnostic, LLM-ready
chart.destroy();API
Props zijn getypeerd als VerticalStackBarChartProps 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() retourneren de renderer-agnostische ChartContext.
Gedragsnotities
Dit gedrag is automatisch (geen extra bedrading nodig) en komt overeen met de legacy michi-vz-grafiek, voor drop-in-pariteit.
Dichte x-as - automatisch draaien / uitdunnen
De band-as meet zijn labels en past zich aan: horizontaal wanneer ze passen, gedraaid −45° (alle labels blijven getoond) wanneer ze niet passen, en uitgedund tot een gelijkmatig verdeelde subset alleen bij extreme dichtheid. De ondermarge wordt automatisch gereserveerd zodat gedraaide labels nooit worden afgesneden. Geen prop nodig - geef xAxisFormat door om de tick-tekst te formatteren (bijv. 202401 → 01-2024).
date accepteert getallen
De date van een rij mag een number zijn (bijv. date: 2024) of een string; de engine dwingt dit af met String(). De bandschaal is scaleBand<string>, dus gemengde types worden consistent genormaliseerd.
keysOrder en kleurvolgorde
keysOrder ("topToBottom" standaard | "bottomToTop") bepaalt aan welk uiteinde van de stapel keys[0] zich bevindt. Met "bottomToTop" is de legenda-/kleurvolgorde omgekeerd ten opzichte van de tekenvolgorde van de stapel - een kleurautoriteit aan de consumentzijde die kleuren toewijst op basis van de volgorde van voorkomen in legendData bindt slot 0 daarom aan de bovenste key, niet aan de onderste. De teken- (pixel)volgorde van de stapel wordt onafhankelijk bepaald en blijft ongewijzigd.
filter - Top/Bottom-N groepen
filter = { limit, sortingDir } rangschikt de DataSets (groepen) op hun totaal over alle rijen + keys en behoudt de top ("desc") of bottom ("asc") limit. Alles stroomafwaarts (keys, datums, y-domein, staven en legenda) wordt afgeleid van de gefilterde set, zodat de legenda altijd exact de getekende staven weerspiegelt.
disabledItems
Namen in disabledItems laten overeenkomende segment-keys en DataSet-groepen vervallen. Het uitschakelen van een groep laat de overige staven breder worden, zodat de band tussen de zichtbare groepen wordt opgesplitst.
tooltipFormatter
Ontvangt { item, key, seriesKey, series, isMissing } - item is de volledige datarij, key het gehoverde segment, series de rijen van het gehoverde segment over alle datums. De ingebouwde tooltip is randbewust: hij klapt naar links van de cursor om bij de rechterrand, en zakt onder de cursor bij de bovenkant, zodat hij nooit buiten het scherm valt.
Interactie (canvas)
Hoveren over een segment dimt de andere segmenten in hetzelfde frame (geen inputvertraging); het verlaten van de grafiek heft de demping op. Klik op een staaf om de tooltip vast te zetten, klik er nogmaals op om opnieuw vast te zetten, en klik buiten de grafiek om los te maken.
