Skip to content

Fontaine (Jet d'Eau)

Expérimental Comparaison

Expérimental - pas encore stable

Contrairement aux 16 autres graphiques (qui sont stables), le graphique Fontaine est expérimental : son API, ses visuels, et la forme de son ChartContext peuvent changer dans les futures versions. C'est une marque de narration / communication, pas un outil d'analyse de précision - voir Quand la Fontaine trouve sa place. Épinglez une version si vous en dépendez.

Genève pompe 500 litres par seconde vers le ciel. Vous photographiez le jet. Vous ne photographiez jamais les tonnes d'eau retombant sans être vues - l'embrun dont la colonne est réellement faite. La plupart des chiffres sont ainsi faits : un pic visible et éclatant, reposant sur une masse cachée que personne ne crédite. Le graphique Fontaine dessine les deux à la fois - le chiffre phare que vous rapportez, et ce qui l'érode discrètement (ou le soutient).

  • Le sommet du jet est le chiffre - lisez-le sur l'axe des y, avec précision. C'est le canal le plus puissant dont dispose un graphique.
  • L'embrun est un signal, pas une règle graduée - « celui-ci saigne / celui-ci est fragile ». Le chiffre secondaire exact vit dans l'infobulle et dans getContext() (spreadRatio), jamais mesuré sur la largeur du panache.

C'est donc un graphique honnête de narration et d'attribution : chiffre d'affaires enregistré vs chiffre d'affaires qui fuit, ventes sécurisées vs pertes, les étoiles que vous voyez vs les mainteneurs que vous ne voyez pas. Ce n'est pas un outil d'analyse de précision - pour cela, tournez-vous vers Éventail (bandes d'incertitude), Barres empilées verticales (sécurisé + à risque triable), ou un waterfall. Voir Quand la Fontaine trouve sa place.

Le style: "jet" par défaut est le Jet d'Eau fidèle : une colonne haute et étroite, dense à la base, s'effilochant en une couronne douce qui dérive sous le vent. Un style: "plume" plus symétrique (une colonne droite avec une éclosion plumeuse et une jupe de brume) est aussi disponible - voir Deux silhouettes.

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

Anatomie : comment lire une fontaine

Chaque partie visible du glyphe a un sens précis. Rien d'autre ne porte de donnée.

  • Le sommet - LE chiffre. Il repose sur un véritable axe des y étiqueté et c'est la seule chose que vous mesurez.
  • La colonne - le corps du chiffre. Décorative ; sa largeur n'encode jamais rien.
  • Couronne / écume - le signal : « celui-ci est fragile / celui-ci saigne ». Large et mousseuse signifie qu'il faut y regarder de plus près ; le second chiffre exact vit dans l'infobulle et dans getContext().jets[].spreadRatio, jamais dans la largeur que vous voyez.
  • Couronne symétrique vs penchée - la symétrie est un signal. Une couronne droite indique que la dispersion est équilibrée (elle pourrait basculer d'un côté comme de l'autre). Une couronne penchée indique que la masse cachée pèse d'un côté - une queue tardive, un risque à la baisse plus lourd. Ne lisez que la direction ; le chiffre d'asymétrie est dans l'infobulle (jets[].lean).
  • Le vent - un jet qui n'encode aucun lean dérive tout de même doucement d'un côté. Cette dérive commune est la signature du Jet d'Eau (le vent sur le lac), purement décorative : tous ces jets dérivent dans le même sens, et lean vaut null dans le contexte.
  • Gouttelettes et brume (style plume) - décoration ; le nombre de gouttelettes évolue avec le champ optionnel density.

Un graphique, deux modes - décidés par le type de l'axe des x. Définissez xAxisDataType: "band" pour le mode Instantané : un jet par catégorie, comparant les magnitudes côte à côte (fontaines, villes, produits). Utilisez un x temporel ou numérique ("date_annual", "date_monthly", "number") pour le mode Tendance : un jet par période, les sommets montants tracent la tendance tandis que chaque panache montre la volatilité de cette période, et un jet de prévision s'affiche en pointillés avec une couronne plus large et plus mousseuse.

Données volumineuses sur WebGPU Expérimental

FountainChart dispose d'un renderer="webgpu" optionnel qui peint la colonne et le panache effiloché de chaque jet comme des marques instanciées sur le GPU tandis que les axes, étiquettes et infobulles restent sur la couche SVG. C'est conditionné par les capacités du navigateur : sur un navigateur sans WebGPU, il rétrograde automatiquement vers canvas, et getContext().renderer indique lequel a effectivement peint. La dérive latérale commune que vous voyez sur les jets est le vent décoratif (aucun de ces éléments n'encode de lean), pas une donnée.

⚗️ 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 jets… detecting

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<FountainChartHandle>(null);

<FountainChart
  ref={ref}
  {...props}
  progressiveDraw={{ durationMs: 2000 }}
/>;
// ref.current?.replay() rejoue l'animation à la demande
vue
<FountainChart :options="{ ...props, progressiveDraw: { durationMs: 2000 } }" />
svelte
<div use:fountainChart={{ ...props, progressiveDraw: { durationMs: 2000 } }}></div>
ts
applyFountainChartProps(this.c.nativeElement, {
  ...props,
  progressiveDraw: { durationMs: 2000 },
});
html
<michi-vz-fountain-chart id="c"></michi-vz-fountain-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.

Faire defiler les annees

Les données couvrent déjà plusieurs années, il n'y a donc rien à taguer. Activez timeline : le bouton lecture et le curseur propres au graphique parcourent ces années - à chaque étape, les jets ne se dessinent que jusqu'à l'année active, et la lecture prolonge la tendance en douceur au fil de l'avancée. Reculez le curseur et la tendance se rétracte en conséquence. Le survol n'inspecte jamais que ce qui est réellement tracé. timeline s'applique au Mode Tendance (x temporel ou numérique) ; le Mode Instantané est catégoriel et n'a pas d'axe des années, donc les jets n'ont pas de date et le contrôle ne s'affiche simplement pas. Désactivé par défaut - sans opt-in, rien ne change.

Appuyez sur le bouton lecture sous le graphique : le graphique se dessine plus loin jusqu'à chaque année au fil de la lecture. Faites glisser le curseur pour sauter à une année.

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

<FountainChart ref={ref} {...props} timeline={{ speedMs: 1000, loop: true }} />;
// ref.current?.timeline() -> play() / pause() / seek(year) / stepForward()
vue
<FountainChart :options="{ ...props, timeline: { speedMs: 1000, loop: true } }" />
svelte
<div use:fountainChart={{ ...props, timeline: { speedMs: 1000, loop: true } }}></div>
ts
applyFountainChartProps(this.c.nativeElement, { ...props, timeline: { speedMs: 1000, loop: true } });
html
<michi-vz-fountain-chart id="c"></michi-vz-fountain-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.
  • 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 valeurs glissent entre les années par défaut (interpolate) ; passez interpolate: false pour des coupes nettes. Avec reduced motion, la coupe est toujours nette.
  • timeline l'emporte sur progressiveDraw quand les deux sont définis sur le même graphique.

Usage

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

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

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

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

// component (uses CUSTOM_ELEMENTS_SCHEMA)
// template: <michi-vz-fountain-chart #c></michi-vz-fountain-chart>
applyFountainChartProps(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-fountain-chart id="c"></michi-vz-fountain-chart>
<script>
  Object.assign(document.getElementById("c"), props); // dataSet, …
</script>
ts
import { mountFountainChart } from "@michi-vz/core";

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

Mode Instantané (x catégoriel)

Passez xAxisDataType: "band" (ou omettez-le ; "band" est la valeur par défaut). Chaque élément de dataSet devient un jet, placé dans sa propre bande x. C'est le mode comparaison : les hauteurs répondent à « lequel est le plus grand ? » et les largeurs de panache répondent à « lequel est le plus incertain ? »

ts
const props = {
  xAxisDataType: "band",
  dataSet: [
    { label: "Jet d'Eau",    value: 140, spread: 20 },
    { label: "King Fahd",    value: 312, spread: 35 },
    { label: "World Cup",    value: 185, spread: 15 },
    { label: "Bellagio",     value:  84, spread:  8 },
  ],
};

Mode Tendance (x temporel ou numérique)

Fournissez un xAxisDataType temporel ou numérique et associez une date à chaque élément. Les jets sont disposés le long de l'axe temporel ; une ligne de tendance relie leurs sommets. Un élément predicted: true s'affiche en pointillés avec un panache visiblement plus mousseux - l'aspect prévision.

ts
const props = {
  xAxisDataType: "date_annual",
  dataSet: [
    { label: "2020", date: 2020, value: 42, spread:  5 },
    { label: "2021", date: 2021, value: 51, spread:  6 },
    { label: "2022", date: 2022, value: 63, spread:  8 },
    { label: "2023", date: 2023, value: 70, spread: 10 },
    { label: "2024", date: 2024, value: 78, spread: 14, predicted: true },
    { label: "2025", date: 2025, value: 85, spread: 20, predicted: true },
  ],
};

Idéal pour 5 à 12 périodes en mode tendance

Avec beaucoup de points de données, les jets se compressent et le graphique se lit comme un graphique en courbes décoré - le détail du panache est perdu. Pour les séries temporelles denses (20+ périodes), préférez le graphique en éventail qui encode l'incertitude sous forme de bandes de confiance lisses. La Fontaine brille à échelle humaine : une poignée de périodes où chaque panache peut respirer.

Guide pratique : façons de lire une fontaine

La fontaine est nouvelle, voici donc le répertoire complet - chaque démo est un graphique réel et vivant avec une légende honnête. Les quatre premières sont les lectures phares (le titre et ce qui l'érode ou le porte discrètement) ; les suivantes généralisent la même grammaire à la certitude, la stabilité, le risque, l'IA et les audiences.

Ventes sécurisées vs pertes

Trois magasins affichent des ventes quasi identiques, un graphique à barres les déclarerait donc égaux. Le panache épais et dense du Magasin C signale où le vol et la démarque érodent la marge, et où envoyer la prévention des pertes en priorité. Le pourcentage de pertes vit dans l'infobulle ; au-delà de 2 % des ventes, c'est le seuil d'alerte.

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

Livré vs jamais facturé (tendance)

Mode tendance : le volume livré continue de grimper, mais le panache qui s'élargit avertit qu'une part croissante n'est jamais facturée - fuites et usage non mesuré dépassant la croissance. Moins de 10 % d'eau non génératrice de revenus, c'est bon ; au-delà de 20 %, il faut agir.

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

Une prévision élevée mais fragile

La tendance monte, mais les jets de prévision s'effilochent en écume pointillée : de la croissance est projetée, et la confiance derrière elle s'amenuise vite. Pour des bandes précises, le graphique en éventail est l'outil adapté ; ceci est la version mémorable du même avertissement.

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

Les étoiles que vous voyez, les mainteneurs que vous ne voyez pas

L'accroche pour laquelle ce graphique a été conçu : le pic est ce que tout le monde voit et met en étoile ; l'embrun est les contributeurs invisibles sur lesquels le projet repose réellement. Notoriété similaire, fondations très différentes. De la narration, pas de la mesure.

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

Même chiffre, trois niveaux de certitude

Trois équipes estiment le même délai de lancement à 72 jours. Sommets identiques ; seul le panache distingue l'équipe qui a mesuré de celle qui a deviné. Le signal indique que le 72 est incertain - la fourchette exacte a sa place dans l'infobulle, et les vrais intervalles de confiance ont leur place dans le graphique en éventail.

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

Stable ou fragile

Deux services affichent une moyenne de 120 ms et deux autres de 60 ms - un graphique à barres montre deux paires de jumeaux. Le panache distingue chaque paire : la couronne resserrée est celle sur laquelle vous pouvez poser un SLO. Ici, un sommet plus bas est préférable ; précisez-le dans la légende si vous l'utilisez. La même lecture fonctionne pour profit vs volatilité.

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

Perte attendue vs pire scénario

Le sommet est la perte attendue ; la couronne s'étend vers le scénario de stress (value + spread, le upperBound dans getContext()). Deux positions anticipent la même perte ; l'une dissimule une queue bien plus lourde. Lisez le pire scénario dans l'infobulle, jamais dans la largeur.

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

Réponses d'IA : confiantes ou hasardeuses

Le sommet est le score de la réponse ; le panache est l'incertitude propre au modèle, normalisée en unités de score pour que les deux partagent l'axe des y. Couronne resserrée : automatisable en toute sécurité. Couronne effilochée : à confier à un humain. La couche insights lit le même spreadRatio dans getContext() pour raconter quelles réponses méritent votre confiance.

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

Même moyenne, audience divisée

Deux articles affichent la même moyenne d'engagement de 5,5 minutes. L'un retient tous ses lecteurs environ ce temps-là ; l'autre partage les siens entre lecteurs pressés et lecteurs assidus. La moyenne masque cette division ; le panache la signale, et ce signal est votre indice pour segmenter avant de tirer la moindre conclusion.

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

De quel côté penche le risque

La symétrie comme signal : trois itinéraires partagent la même médiane et la même dispersion, mais une couronne penche - ses surprises sont unilatérales, une queue tardive (lean: 0.8). Droite (lean: 0) signifie équilibrée ; penchée signifie que la masse cachée pèse de ce côté-là. Ne lisez que la direction, jamais l'angle.

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

Typhons sur les Philippines

Parfois l'inclinaison est littérale. Chaque jet est un typhon : le sommet donne les vents soutenus maximaux, l'embrun s'étire vers les rafales (mêmes km/h), l'épaisseur de l'écume traduit la taille du champ de vents, et la couronne penche dans le sens du déplacement de la tempête - les typhons du Pacifique traversent les Philippines d'est en ouest, toute la ligne penche donc vers la gauche, et celui qui a bifurqué vers le Japon penche de l'autre côté. Un seul glyphe, quatre canaux honnêtes, zéro nouveau type de graphique.

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

Deux silhouettes

Définissez style pour choisir la forme ; les deux encodent les mêmes données (sommet = value, canal de dispersion = spread).

  • style: "jet" (par défaut) - le Jet d'Eau fidèle : une colonne haute et étroite, dense et opaque à la base, s'effilochant en une couronne douce et translucide au sommet (construite à partir de couches d'opacité graduée ; la largeur de la couronne croît avec spread, le nombre de couches avec le density optionnel). lean (dans [-1, 1]) fait dériver la couronne sous le vent. Iconique ; idéal comme titre / indicateur clé ou pour une comparaison.
  • style: "plume" - une colonne symétrique s'épanouissant en une couronne plumeuse : frothLayers tranches d'opacité graduée au sommet, une jupe showMist douce, et des arcs balistiques showDroplets. stemFraction et bloomExponent ajustent le profil colonne-vers-couronne. Plus épuré pour un indicateur clé unique où la dispersion se lit comme un halo de confiance.
ts
const props = { style: "plume", dataSet: [{ label: "Q4", value: 78, spread: 20 }] };
Example
canvas · responsive
Aller plus loin : Guide Insights·Guide DevTools

Règle empirique : plume pour peu de jets, jet pour le héros et les données volumineuses. À échelle humaine (1 à 12 jets), la couronne symétrique en couches du style plume est la forme la plus facile pour lire le symptôme - halo resserré vs écume large. Sur des centaines de jets, l'éclosion de la plume se retrouve réduite à un fragment de l'emplacement et se dégrade en simple barre, tandis que le jet à colonne dominante se dégrade avec élégance en une longue bande (voir la démo de données volumineuses ci-dessus) ; il porte aussi la marque. Pour des séries véritablement denses, arrêtez de décorer et tournez-vous vers le graphique en éventail.

La symétrie porte du sens. Une couronne droite (le style plume, ou un jet avec lean: 0) indique que la dispersion est équilibrée. Une couronne penchée (lean dans [-1, 1], seul le signe compte) indique que la dispersion penche d'un côté. Un jet sans lean conserve une légère dérive décorative - le vent de Genève - et indique lean: null dans le contexte, pour que les consommateurs puissent distinguer le signal de l'ornement.

Les deux styles partagent stemFraction (demi-largeur de la base de la colonne en fraction de l'emplacement), le champ density, et lean. Les couleurs suivent vos données / colorsMapping ; l'écume/l'embrun ne module que l'opacité de votre teinte, pour que le graphique s'adapte aux thèmes clair et sombre.

Quand la Fontaine trouve sa place

La littérature a été vérifiée avant la publication de ce graphique. La métaphore du Jet d'Eau est nouvelle en dataviz (aucun graphique fontaine/jet préexistant), et l'idée sous-jacente est une réorientation solide de la famille raincloud / violin / density-strip. Mais sa fonction honnête est la communication, pas la mesure - alors utilisez-la là où un titre mémorable accompagné de sa moitié cachée compte, et tournez-vous vers un graphique de précision quand vous devez comparer le second chiffre exactement.

Bons usages

  • Titre phare vs érosion cachée. Chiffre d'affaires enregistré vs qui fuit (l'écart de rétention brut-à-net), ventes sécurisées vs pertes, capacité vs pertes. Une seule marque dit « voici le chiffre, et voici ce qui saigne en dessous ». C'est son usage phare.
  • Élevé mais fragile / poussé artificiellement haut. Une barre montre le niveau ; l'embrun ajoute « et voici à quel point c'est fragile ».
  • Narration « ce que vous voyez vs ce que ça a coûté » - la victoire visible et le travail invisible derrière. Elle l'emporte sur la reconnaissance et le rappel (la seule chose que la recherche sur l'embellissement confirme).

Utilisez-la honnêtement

  • Le sommet est la seule chose que les lecteurs mesurent. Placez-y le chiffre phare, sur un véritable axe des y étiqueté. La largeur et l'aire sont des canaux à faible précision (les gens les sous-estiment), donc ne demandez jamais à personne de comparer des largeurs d'embrun.
  • L'embrun est un signal ; le chiffre est du texte. Faites apparaître le second chiffre exact dans l'infobulle / la légende / getContext().jets[].spreadRatio, et ancrez-le dans un seuil déclaré (pertes > 2 %, NRR < 100 %, eau non génératrice de revenus > 20 %, P10-P90).
  • Privilégiez le mode instantané ; limitez le mode tendance à une poignée de périodes. Pour un travail d'incertitude dense ou précis, préférez Éventail (bandes), Barres empilées verticales (sécurisé + à risque triable), ou un waterfall.
  • Limitez-vous à 5-12 glyphes et triez les instantanés par spreadRatio pour que l'élément le plus mousseux soit facile à trouver.

API

Les props sont typées comme FountainChartProps 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. Référence complète : API Fountain.