Vergelijkbare staven
Vergelijking
Werd het beter of slechter? Zet voor en na naast elkaar op één balk per label, en het verschil dat gedicht (of geopend) is, is het eerste wat de lezer ziet.
De grafiek hierboven gebruikt in elk framework dezelfde engine - alleen de integratiecode hieronder verschilt.
Zware datasets op WebGPU Experimenteel
ComparableHorizontalBarChart heeft een optionele renderer="webgpu" die de twee subbalken per rij tekent als GPU-instanced rechthoeken, terwijl assen, labels en tooltips op de SVG-laag blijven. Dit is capability-gated: in een browser zonder WebGPU schakelt het automatisch terug naar canvas, en getContext().renderer meldt welke renderer daadwerkelijk heeft getekend.
Speel door de jaren heen
Geef elke rij een date en zet timeline aan: het staafdiagram wordt een verhaal per jaar, met een eigen afspeelknop en scrubber die telkens het voor/na-verschil van één periode toont. 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<ComparableHorizontalBarChartHandle>(null);
<ComparableHorizontalBarChart ref={ref} {...props} timeline={{ speedMs: 1000, loop: true }} />;
// ref.current?.timeline() -> play() / pause() / seek(year) / seekIndex(i) / stepForward()<ComparableHorizontalBarChart :options="{ ...props, timeline: { speedMs: 1000, loop: true } }" /><div use:comparableHorizontalBarChart={{ ...props, timeline: { speedMs: 1000, loop: true } }}></div>applyComparableHorizontalBarChartProps(this.c.nativeElement, { ...props, timeline: { speedMs: 1000, loop: true } });<michi-vz-comparable-horizontal-bar-chart id="c"></michi-vz-comparable-horizontal-bar-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.- Een
filter(top-N, sortering) blijft binnen elke periode gelden, dus een "top 5 per jaar" werkt meteen. - Rijen zonder
dateblijven in elke periode zichtbaar.
Hoekradius
Elke balk krijgt standaard hoeken van 5px. Op een klein scherm worden de balken dun - de halve banden van de grouped-layout zijn soms maar zo'n 10px dik - en een radius van 5px op een balk van 10px maakt er een pil van. barRadius stelt de radius in px in: 0 voor vierkante hoeken, 2-4 voor bijna vierkante.
barRadius: 5 (standaard)barRadius: 2barRadius: 0Dezelfde grafiek, dezelfde data; alleen barRadius verandert. Wissel van renderer: svg en canvas ronden de hoeken identiek af.
<ComparableHorizontalBarChart {...props} layout="grouped" barRadius={2} /><ComparableHorizontalBarChart :options="{ ...props, layout: 'grouped', barRadius: 2 }" /><div use:comparableHorizontalBarChart={{ ...props, layout: "grouped", barRadius: 2 }}></div>applyComparableHorizontalBarChartProps(this.c.nativeElement, { ...props, layout: "grouped", barRadius: 2 });<michi-vz-comparable-horizontal-bar-chart layout="grouped" bar-radius="2"></michi-vz-comparable-horizontal-bar-chart>- De getekende radius is nooit groter dan de helft van de breedte of hoogte van de balk, in svg en canvas gelijk.
- Zonder
barRadiusblijft het vertrouwde uiterlijk van 5px behouden. Een negatieve waarde geeft vierkante hoeken. - De experimentele
webgpu-renderer tekent vierkante hoeken, wat de waarde ook is.
Gebruik
import { ComparableHorizontalBarChart } from "@michi-vz/react";
export default () => <ComparableHorizontalBarChart {...props} />; // props = the chart options<script setup>
import { ComparableHorizontalBarChart } from "@michi-vz/vue";
</script>
<template>
<ComparableHorizontalBarChart :options="props" />
</template><script>
import { comparableHorizontalBarChart } from "@michi-vz/svelte";
</script>
<div use:comparableHorizontalBarChart={props}></div>// main.ts - register the elements once
import "@michi-vz/angular";
import { applyComparableHorizontalBarChartProps } from "@michi-vz/angular";
// component (uses CUSTOM_ELEMENTS_SCHEMA)
// template: <michi-vz-comparable-horizontal-bar-chart #c></michi-vz-comparable-horizontal-bar-chart>
applyComparableHorizontalBarChartProps(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-comparable-horizontal-bar-chart id="c"></michi-vz-comparable-horizontal-bar-chart>
<script>
Object.assign(document.getElementById("c"), props); // dataSet/series, title, …
</script>import { mountComparableHorizontalBarChart } from "@michi-vz/core";
const chart = mountComparableHorizontalBarChart(el, props);
chart.update(next);
chart.getContext(); // renderer-agnostic, LLM-ready
chart.destroy();API
Props zijn getypeerd als ComparableHorizontalBarChartProps 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
Twee subbalken per rij
Elke rij tekent valueBased (licht) en valueCompared (vol), divergerend vanaf x=0; de kortste subbalk wordt bovenop getekend, zodat beide waarden zichtbaar blijven welke kant de waarde ook op ging. colorsBasedMapping geeft de valueBased-subbalk per label een eigen kleur: combineer een dekkende lichte tint met valueBasedOpacity: 1 (zoals de demo hierboven) voor het scherpste voor/na-contrast in beide thema's. valueBasedOpacity / valueComparedOpacity stellen hun vulopaciteit in. Een subbalk waarvan de opgeloste vulling transparent is, wordt overgeslagen (consumenten verbergen zo de helft via CSS). minBarWidth (standaard 5) zorgt voor een ondergrens op een niet-nul balk, zodat waarden dicht bij nul zichtbaar blijven.
patternsMapping - arcering / afbeeldingsvullingen
patternsMapping: Record<label, imageSrc> vult de value-based subbalk met een herhaalde afbeelding in plaats van een vlakke kleur. createHatchPattern({ color, angle?, spacing?, strokeWidth? }) (geëxporteerd uit @michi-vz/core en @michi-vz/react) geeft voor het gangbare geval een diagonale arcering terug als SVG data-URI. De canvas-renderer herhaalt deze via ctx.createPattern en rendert opnieuw zodra de afbeelding geladen is.
Waarde-as (x)
xAxisPredefinedDomain: [min, max] legt het bereik van de waarde-as vast (alias van xAxisDomain). showZeroLineForXAxis tekent een doorgetrokken lijn op x=0 (divergerende grafieken); showGrid schakelt verticale rasterlijnen in/uit (standaard uit). xAxisFormat formatteert de tick-labels.
Labelkolom (y)
De categorielabels van de y-as staan in een linkerkolom van tickHtmlWidth px breed (standaard 100, met ellips). padding.left verschuift het plot (balken + waarde-as) naar rechts ZONDER de labels te verplaatsen - zodat er ruimte ontstaat voor een brede labelkolom. horizontalTickPosition: { x, y } verschuift de labels zodat ze aansluiten op een externe legenda. hideTickLabels verbergt ze volledig (wanneer de categorienamen al in een legenda staan).
Tooltip
tooltipFormatter(datum, dataSet, type) ontvangt de rij waarover gehoverd wordt, alle rijen, en het type van de gehoverde subbalk ("based" | "compared"). Het geeft een HTML-string terug; de React-wrapper accepteert daarnaast ook een React-node (omgezet naar statische HTML). De ingebouwde tooltip is edge-aware (klapt om nabij de rechter-/bovenrand).
Laden / geen data + interactie
isLoading en isNodata sturen de overlay aan (React: isLoadingComponent / isNodataComponent). Hoveren markeert een rij (andere dimmen) en mouseleave maakt dit ongedaan; de balken zijn afgerond (standaard radius 5, in te stellen met barRadius) met een rand van 1px.
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 (het opnieuw uitzenden van een ongewijzigde context bij elke render kan een consument die op elke aanroep dispatcht in een lus laten belanden).
