Skip to content

Treemap

Composition

« Quelles parties sont les plus grosses, et quelle part de chacune est déjà réalisée ? » Un treemap répond aux deux à la fois : chaque tuile est dimensionnée selon son total, et une division optionnelle en deux parties remplit la part solide à l'intérieur de chaque tuile - vous lisez ainsi l'ampleur (l'aire) et la progression (la division) en un seul coup d'œil. Le cas classique est le potentiel d'exportation : l'aire de la tuile = le potentiel total, la partie solide = réalisé, la partie plus claire = inexploité. Les tuiles peuvent s'imbriquer sous des groupes, et sur un écran étroit, l'ensemble se replie en une pile lisible sur une seule colonne.

Example
canvas · responsive
Aller plus loin : Guide Insights·Guide DevTools

Vous préférez une liste plate (une tuile par produit, chacune sa propre couleur - la disposition classique du potentiel d'exportation) ? Retirez l'imbrication children et passez les feuilles directement :

Example
canvas · responsive
Aller plus loin : Guide Insights·Guide DevTools

La division est générique. Nommez les deux parties avec splitLabels - ["Realized", "Untapped"], ["Used", "Free"], ["Done", "Remaining"] - rien dans le moteur ne code en dur un domaine.

Quand le choisir

  • Vues de portefeuille. Des centaines de produits, secteurs ou centres de coûts sur un seul écran : l'aire est la taille, la division est la progression, et toute la hiérarchie tient sans défilement.
  • « Où devrions-nous concentrer nos efforts ? » Les grandes tuiles majoritairement inexploitées forment la liste des opportunités, sans tri nécessaire - la lecture classique du potentiel d'exportation et de l'analyse de marché.
  • Une douzaine de catégories plates ou moins ? Une barre ou un camembert lit les valeurs exactes plus vite que des aires de tuiles ; le treemap gagne sa place à grande échelle.

Données volumineuses sur WebGPU Expérimental

TreemapChart possède un renderer="webgpu" optionnel qui dessine les tuiles comme des rectangles rendus par le GPU tandis que les libellés, les infobulles et le remplissage de la division restent sur la couche SVG. Il est conditionné aux capacités du navigateur : sur un navigateur sans WebGPU, il bascule automatiquement sur canvas, et getContext().renderer indique lequel a effectivement dessiné.

⚗️ Experimental - not yet stable. WebGPU rendering is an opt-in preview. It needs a WebGPU-capable browser (Chrome / Edge, or Safari 26+); everywhere else it falls back to canvas automatically. Axes, labels and tooltips stay on the SVG layer - only the data marks are painted on the GPU.
Heavy-data demo · ~400 tiles… detecting

Faire defiler les annees

Étiquetez chaque tuile de premier niveau avec une date et activez timeline : l'instantané d'une année est constitué des tuiles racines partageant cette date - les enfants n'ont pas besoin de leur propre date - et les tuiles glissent d'une année à l'autre en changeant de taille. Désactivé par défaut - sans opt-in, rien ne change. C'est un défilement interactif année par année, pas l'entrée ponctuelle plus bas.

Appuyez sur le bouton lecture sous le graphique : les données défilent année par année, un instantané à la fois. Faites glisser le curseur pour sauter à une année.

tsx
const ref = useRef<TreemapChartHandle>(null);

<TreemapChart ref={ref} {...props} timeline={{ speedMs: 1000, loop: true }} />;
// ref.current?.timeline() -> play() / pause() / seek(year) / stepForward()
vue
<TreemapChart :options="{ ...props, timeline: { speedMs: 1000, loop: true } }" />
svelte
<div use:treemapChart={{ ...props, timeline: { speedMs: 1000, loop: true } }}></div>
ts
applyTreemapChartProps(this.c.nativeElement, { ...props, timeline: { speedMs: 1000, loop: true } });
html
<michi-vz-treemap-chart id="c"></michi-vz-treemap-chart>
<script>
  const el = document.getElementById("c");
  el.timeline = { speedMs: 1000, loop: true };
  // el.getTimeline() -> play() / pause() / seek(year)
</script>
  • speedMs règle le rythme, loop reboucle, autoplay: true démarre au montage, showControl: false masque la barre intégrée.
  • Les valeurs glissent d'une période à l'autre par défaut (interpolate) ; ajustez le mouvement avec tweenMs et easing, ou passez interpolate: false pour des coupes nettes. Avec reduced motion, la coupe est toujours nette.
  • Le contrôleur headless reste disponible : chart.timeline() expose play() / pause() / toggle() / seek(period) / stepForward() / stepBack(), plus onStep et formatPeriod dans la config pour une UI maison.
  • Les tuiles racines sans date restent visibles à chaque période.
  • timeline l'emporte sur progressiveDraw quand les deux sont définis - l'animation de révélation plus bas reste inactive tant que le timeline garde la main.

Animation de révélation

Le graphique se dessine de gauche à droite au montage, révélant ses éléments dans l'ordre avant de se stabiliser. Désactivé par défaut - un graphique l'active avec la prop progressiveDraw.

Chaque ligne grandit de la première à la dernière année ; l'étiquette suit la pointe puis se pose à l'extrémité de la ligne. Avec reduced motion activé, le graphique s'affiche entièrement tracé, instantanément.

progressiveDraw: true applique les réglages par défaut (1200 ms, easeInOutCubic). Un objet de configuration affine le comportement :

tsx
const ref = useRef<TreemapChartHandle>(null);

<TreemapChart
  ref={ref}
  {...props}
  progressiveDraw={{ durationMs: 2000 }}
/>;
// ref.current?.replay() rejoue l'animation à la demande
vue
<TreemapChart :options="{ ...props, progressiveDraw: { durationMs: 2000 } }" />
svelte
<div use:treemapChart={{ ...props, progressiveDraw: { durationMs: 2000 } }}></div>
ts
applyTreemapChartProps(this.c.nativeElement, {
  ...props,
  progressiveDraw: { durationMs: 2000 },
});
html
<michi-vz-treemap-chart id="c"></michi-vz-treemap-chart>
<script>
  const el = document.getElementById("c");
  el.progressiveDraw = { durationMs: 2000 };
  // el.replay() rejoue l'animation
</script>
  • durationMs et easing ("linear", "easeOutQuad", "easeInOutCubic", ou une fonction (t) => t personnalisée) façonnent le rythme du tracé.
  • autoplay: false rend le graphique entièrement tracé ; appelez replay() (handle de ref React, méthode du web component ou instance core) pour lancer l'animation à la demande. replayOnUpdate: true la rejoue à chaque changement de données.
  • Respecte prefers-reduced-motion : le graphique s'affiche alors entièrement tracé, instantanément.
  • L'animation de révélation est une entrée ponctuelle ; le défilement par année ci-dessus avance plutôt année par année.

Utilisation

tsx
import { TreemapChart } from "@michi-vz/react";

export default () => <TreemapChart {...props} />; // props = the chart options
vue
<script setup>
import { TreemapChart } from "@michi-vz/vue";
</script>

<template>
  <TreemapChart :options="props" />
</template>
svelte
<script>
  import { treemapChart } from "@michi-vz/svelte";
</script>

<div use:treemapChart={props}></div>
ts
// main.ts - register the elements once
import "@michi-vz/angular";
import { applyTreemapChartProps } from "@michi-vz/angular";

// component (uses CUSTOM_ELEMENTS_SCHEMA)
// template: <michi-vz-treemap-chart #c></michi-vz-treemap-chart>
applyTreemapChartProps(this.c.nativeElement, props);
html
<script type="module" src="https://cdn.jsdelivr.net/npm/@michi-vz/wc/dist/michi-vz-wc.bundle.js"></script>

<michi-vz-treemap-chart id="c"></michi-vz-treemap-chart>
<script>
  Object.assign(document.getElementById("c"), props); // dataSet, splitLabels, …
</script>
ts
import { mountTreemapChart } from "@michi-vz/core";

const chart = mountTreemapChart(el, props);
chart.update(next);
chart.getContext(); // renderer-agnostic, LLM-ready
chart.destroy();

Forme des données

Chaque nœud de dataSet est soit une feuille (value, partial optionnel), soit un parent (children). La valeur d'un parent est la somme de ses feuilles.

ts
const props = {
  splitLabels: ["Realized", "Untapped"],
  showLegend: true,
  layout: "auto", // squarify on desktop, stack on narrow screens
  dataSet: [
    { label: "Agri-food", children: [
      { label: "Fruits", value: 100, partial: 34 },   // 34% realized
      { label: "Beverages", value: 50, partial: 35 }, // 70% realized
    ]},
    { label: "Industry", children: [
      { label: "Machinery", value: 120, partial: 64 },
    ]},
  ],
};

Disposition adaptative

layout choisit l'algorithme de pavage : "squarify" (le treemap), "stack" (une partition verticale en une seule colonne - lignes pleine largeur, hauteur proportionnelle à la valeur, avec la même division dans chaque ligne), ou "auto" (passe en pile en dessous de stackBreakpoint, 480px par défaut). La division, les libellés, l'infobulle, getContext() et la parité SVG/canvas sont identiques dans les deux dispositions.

API

Les props sont typées comme TreemapChartProps dans @michi-vz/core. Communes à tous les graphiques : width, height, margin, colors / colorsMapping, renderer ("svg", "canvas", ou "webgpu" expérimental), highlightItems, disabledItems, et les callbacks on*. onChartDataProcessed / getContext() renvoient le ChartContext indépendant du moteur de rendu. Référence complète : API Treemap.