API Đài phun (Jet d'Eau)
Mỗi cột một con số (chấm lớn), khoảng thật xung quanh nó (đài phun, từ low đến high) và chính các lần đo (các chấm nhỏ), tất cả trên cùng một trục y. Trục x theo danh mục = ảnh chụp nhanh (snapshot); trục x theo thời gian hoặc số = xu hướng (trend). Xem demo Đài phun và cách đọc.
Nhập
import "@michi-vz/wc/fountain-chart";
// <michi-vz-fountain-chart> đã được định nghĩaimport { mountFountainChart } from "@michi-vz/core";
const chart = mountFountainChart(el, props);import { FountainChart } from "@michi-vz/react/fountain-chart";import { FountainChart } from "@michi-vz/vue/fountain-chart";import { fountainChart } from "@michi-vz/svelte/fountain-chart";import { bindChart, applyFountainChartProps } from "@michi-vz/angular/fountain-chart";
// cần CUSTOM_ELEMENTS_SCHEMA trên component chứa <michi-vz-fountain-chart>Props
| Prop | Type | Default | Description |
|---|---|---|---|
timeline | boolean | TimelinePeriodConfig | - | Opt-in "play through years" (cumulative): the marks draw UP TO the active period and extend as the timeline steps; `interpolate` sweeps smoothly between years, `false` jump-cuts. Headless controller via `chart.timeline()` plus the built-in play button + scrubber. Off by default; wins over `progressiveDraw` when both are set. The reveal always shows the whole active jet, fountain and small dots included, and a jet's value labels appear with it; undrawn jets cannot be hovered. Trend mode only. Not drawn by the "webgpu" renderer (an ignored-option warning). |
progressiveDraw | boolean | ProgressiveDrawConfig | - | Opt-in reveal animation: wipes the marks in left to right on mount (a clip reveal; axes and titles stay put). `true` uses defaults (1200 ms, easeInOutCubic); a config tunes durationMs, easing, autoplay, and replayOnUpdate (`tipLabel` is LineChart-only and ignored here). Off by default; respects prefers-reduced-motion (renders fully drawn instantly) and `replay()` re-runs it. Jets the wipe has not reached cannot be hovered. Not drawn by the "webgpu" renderer (an ignored-option warning). |
dataSet* | FountainDataItem[] | - | Array of jets; each item renders one fountain |
title | string | - | Optional chart title rendered above the plot |
xAxisDataType | FountainXAxisType | - | How the x-axis is parsed: a temporal/numeric type renders TREND mode (jets at their dates, the x range inset by half a column on each side, one tick per period); "band" (or omitted) renders SNAPSHOT mode (one column per label) |
yAxisDomain | [number, number] | - | Explicit [min, max] for the value (y) axis, used as given (not rounded). The auto domain includes 0, every value, low, high and reference line, plus 10% headroom, rounded to nice ticks. Data outside a user domain is clamped to the plot edge and small dots outside it are not drawn (an `out-of-domain` warning). |
xAxisFormat | (d: number | string) => string | - | Formats an x tick value into its display label |
yAxisFormat | (d: number | string) => string | - | Formats a y value: the tick labels and the numbers in the value labels and the tooltip (default: the locale's number format) |
ticks | number | 5 | Approximate number of axis ticks to generate (default 5) |
tickValues | Array<number | Date> | - | Explicit x tick values, overriding the per-period ticks (trend mode) |
showRange | boolean | true | Draw the fountain: the range [low, high] as a bell (default true). `false` draws the stem and the big dot only; the small dots need the fountain to sit in, so they hide too. |
showSamples | boolean | true | Draw the small dots, one per sample, when items carry `samples` (default true) |
showValueLabels | boolean | true | Print value labels under each x label (default true): bold "usual 30", then "<low word> 22" and "<high word> 55" (see `endLabels`), "only N <sampleWord>" under 10 samples, and per reference line with a `goodSide` a bold "17 of 20" plus its `countLabel`. The chart reserves bottom margin for them. On narrow columns the text shrinks, then the end lines go, before a label would overlap a neighbour; when even the usual line cannot fit, when the x labels have to tilt, or where two jets share a column, the value labels are left out (a `layout-overflow` warning). |
drift | boolean | false | The Geneva look: the top of every fountain leans downwind, the same way for every jet, so it means nothing (default false: readers found it confusing) |
yAxisTitle | string | - | Title drawn rotated beside the y-axis, e.g. "minutes (higher = slower)" |
endLabels | [string, string] | - | Words for the low and high ends in the value labels and tooltip (default ["lowest", "highest"]; e.g. ["best", "worst"], ["cheapest", "dearest"]) |
referenceLines | FountainReferenceLine[] | - | Horizontal reference lines (a promise, a limit, a budget). With `goodSide`, each jet with samples counts its small dots on the good side. |
labels | FountainLabels | - | UI words for localisation (English defaults "usual", "of", "only", "forecast") |
readingGuide | boolean | string | - | A reading guide under the plot (default false), on one line when it fits, else wrapped between its rules (at each " · "), never inside one. `true` prints the default ("Small dot = one measurement · Big dot = the usual one · Dots close together = steady · Tall fountain = changes a lot · Few dots = just a guess") with only the rules for marks the chart draws: no small-dot rules without small dots (no samples, showSamples or showRange off, forecasts only), no "Tall fountain" rule without a fountain. A string replaces it and is printed as given. |
sampleWord | string | - | PLURAL noun for the samples in the value labels and tooltip, e.g. "days", "orders" (default "measurements"). Plural on purpose: there is no pluralising logic, and one string is easy to localise. |
showTrendLine | boolean | - | Draw a dashed grey line through the big dots, left to right (default true in trend mode with one series; false with several series, where one line would zig-zag between them, and in snapshot mode; set it true to join an ordered sequence of categories, e.g. hours) |
tooltipFormatter | (d: FountainDataItem & { value: number }, jet?: FountainTooltipJet) => string | - | Returns custom tooltip HTML for a hovered or pinned jet (sanitized before it is inserted). Default: the label (with its period in trend mode), "usual 30", "<low word> 22 · <high word> 55", "20 <sampleWord>" and a count per reference line with a goodSide, numbers formatted like the y-axis. Click or tap pins the tooltip; clicking the pinned jet or empty space, or Escape, unpins. The first argument is the item with its resolved `value` (the median of its samples when it gives none), so `d.value` is always a number; a formatter typed `(d: FountainDataItem) => string` still fits. The second is the jet as drawn (its range, samples, reference counts, period and the default lines), so a custom tooltip needs no re-derivation. |
isLoading | boolean | - | Show the loading overlay; with nothing drawn yet the axes and marks wait for data, while a refetch keeps the stale jets on screen. |
isNodata | boolean | ((dataSet: FountainDataItem[] | null | undefined) => boolean) | - | No-data override: boolean, or a predicate on the data; default = an empty dataSet. With no data the chart draws the no-data overlay instead of axes and marks. |
noDataLabel | string | - | Text for the vanilla default no-data overlay (ignored when suppressed). |
suppressDefaultOverlay | boolean | - | A framework wrapper sets this to render its OWN loading/no-data node instead. |
onHighlightItem | (labels: string[]) => void | - | Called when the hovered, pinned or cleared label changes (only on a change: moving within one jet does not re-fire; leaving every jet fires []) |
style | "jet" | "plume" | - | Deprecated ignored since core 1.29; emits an ignored-option warning. There is one look now: stem, fountain, small dots, big dot. |
frothLayers | number | - | Deprecated ignored since core 1.29; emits an ignored-option warning |
bloomExponent | number | - | Deprecated ignored since core 1.29; emits an ignored-option warning |
stemFraction | number | - | Deprecated ignored since core 1.29; emits an ignored-option warning |
showDroplets | boolean | - | Deprecated ignored since core 1.29; emits an ignored-option warning |
showMist | boolean | - | Deprecated ignored since core 1.29; emits an ignored-option warning |
Common props - shared by every chart (14)
| Prop | Type | Default | Description |
|---|---|---|---|
width | number | 900 | Chart width in pixels |
height | number | 480 | Chart height in pixels |
margin | Margin | { top: 50, right: 40, bottom: 50, left: 60 } | Inner margins (top/right/bottom/left, in px); default 8 (36 top with a title) |
colors | string[] | - | Categorical palette for rings without an explicit colour or colorsMapping entry |
colorsMapping | Record<string, string> | - | Explicit label -> colour map; takes precedence over the palette and per-item colours |
highlightItems | string[] | - | Labels to emphasise (active styling); others keep their base opacity |
disabledItems | string[] | - | Labels to hide entirely (ring + track removed; remaining rings keep their radii order) |
renderer | "svg" | "canvas" | "webgpu" | "svg" | Render as inline SVG (default) or to a canvas / WebGPU layer; getContext() is identical either way |
locale | string | - | BCP-47 locale used for number formatting |
skipColorMappingDispatch | boolean | false | External-CSS mode: unmapped labels resolve to transparent and onColorMappingGenerated is not emitted, so arc colours come from your CSS via the data-label-safe contract |
enableTransitions | boolean | true | Animate opacity/arc changes with CSS transitions (SVG renderer; default true) |
onColorMappingGenerated | (mapping: Record<string, string>) => void | - | Called with the resolved label -> colour map after the chart assigns colours |
onChartDataProcessed | (context: ChartContext) => void | - | Called with the renderer-agnostic ChartContext whenever the data is (re)processed |
onDataWarning | (warnings: DataWarning[]) => void | - | Called with any non-fatal data warnings (out-of-range values, duplicate labels, ...) |
Hai chế độ, một cấu trúc dữ liệu
Đặt xAxisDataType: "band" (hoặc bỏ qua) cho chế độ ảnh chụp nhanh: mỗi label một cột. Đặt xAxisDataType theo thời gian hoặc số cùng một date trên mỗi mục cho chế độ xu hướng: các tia nằm dọc trục x và, khi chỉ có một chuỗi, một đường đứt nét nối các chấm lớn. Một mục forecast: true có thân và viền đứt nét, phần tô nhạt hơn và chấm lớn rỗng, không có chấm nhỏ.
Mới trong core 1.29
| Prop | Kiểu | Mặc định | Tác dụng |
|---|---|---|---|
showRange | boolean | true | Vẽ đài phun, tức khoảng [low, high]. false chỉ vẽ thân và chấm lớn; các chấm nhỏ cũng ẩn theo. |
showSamples | boolean | true | Vẽ mỗi lần đo một chấm nhỏ, khi các mục có samples. |
showValueLabels | boolean | true | Ghi dưới mỗi nhãn x: "usual 30" in đậm, "<từ đầu thấp> 22", "<từ đầu cao> 55", "only N <sampleWord>" khi dưới 10 lần đo, và với mỗi đường tham chiếu có goodSide là "17 of 20" in đậm kèm countLabel. |
drift | boolean | false | Kiểu Geneva: phần trên của mỗi đài phun nghiêng về cùng một phía. Nó không mang dữ liệu nào. |
yAxisTitle | string | không có | Tiêu đề xoay dọc bên cạnh trục y, ví dụ "phút (cao hơn = chậm hơn)". |
endLabels | [string, string] | ["lowest", "highest"] | Từ cho đầu thấp và đầu cao trong nhãn giá trị và tooltip. |
referenceLines | FountainReferenceLine[] | không có | Các đường đứt nét màu cảnh báo của theme, nhãn ở đầu bên phải. Xem bên dưới. |
labels | FountainLabels | tiếng Anh | Các từ khác của biểu đồ, để dịch. Xem bên dưới. |
readingGuide | boolean | string | false | Hướng dẫn đọc dưới biểu đồ, xuống dòng giữa các quy tắc (tại mỗi dấu « · ») khi không vừa một dòng. true dùng hướng dẫn mặc định, chỉ nêu những gì biểu đồ vẽ (không có quy tắc về chấm nhỏ khi không có chấm nhỏ, không có Tall fountain khi không có đài phun); một chuỗi sẽ thay thế nó. |
sampleWord | string | "measurements" | Danh từ số nhiều cho các lần đo ("days", "orders"). Cố ý dùng số nhiều: không có logic tự chia số nhiều. |
showTrendLine giờ có mặc định theo chế độ: true ở chế độ xu hướng với một chuỗi; false khi có nhiều chuỗi, vì một đường duy nhất sẽ chạy zíc zắc qua lại giữa các chuỗi, và ở chế độ ảnh chụp nhanh (đặt true để nối một dãy danh mục có thứ tự).
Mục dữ liệu: FountainDataItem
| Trường | Kiểu | Ý nghĩa |
|---|---|---|
label | string | Cột (ảnh chụp nhanh) hoặc tên chuỗi (xu hướng). Quyết định màu và hook data-label. |
code | string | Mã cố định tùy chọn, được đưa vào context; không hiển thị. |
value | number | Chấm lớn. Không bắt buộc khi có samples: khi đó là trung vị của chúng. Không có giá trị hữu hạn và không có lần đo thì tia bị bỏ qua. |
low | number | Đáy của đài phun. |
high | number | Đỉnh của đài phun. |
spread | number | Cách viết tắt cho một khoảng đều: low = value - spread, high = value + spread. |
samples | number[] | Các lần đo thật, mỗi lần một chấm nhỏ, nằm đúng độ cao bên trong đài phun. |
forecast | boolean | Một kỳ dự báo: thân và viền đứt nét, phần tô nhạt hơn, chấm lớn rỗng, không có chấm nhỏ và không có số đếm. |
color | string | Màu riêng cho mục. Thứ tự cho mỗi tia: colorsMapping[label], rồi color, rồi màu bảng màu của nhãn. |
date | number | string | Vị trí trên trục x ở chế độ xu hướng; mục không có ngày dùng được sẽ bị bỏ qua ở đó. |
predicted | boolean | Đã lỗi thời: dùng forecast. Vẫn được xử lý. |
certainty | boolean | Đã lỗi thời: certainty: false tương đương forecast: true. Vẫn được xử lý. |
density | number | Đã lỗi thời và bị bỏ qua (cảnh báo ignored-option). |
lean | number | Đã lỗi thời và bị bỏ qua (cảnh báo ignored-option). |
Khoảng được lấy theo thứ tự: low/high, rồi spread, rồi lần đo thấp nhất và cao nhất; không có cái nào thì tia không có đài phun. Một đầu bị thiếu cũng theo thứ tự đó. Lần đo nằm ngoài khoảng đã cho, và giá trị nằm ngoài khoảng, sẽ nới rộng khoảng và gửi một cảnh báo. Giá trị âm vẫn được: miền y bao gồm 0 và mọi low, và thân chạy xuống từ đường gốc.
Đường tham chiếu: FountainReferenceLine
| Trường | Kiểu | Ý nghĩa |
|---|---|---|
value | number | Vị trí của đường, theo đơn vị trục y. Luôn nằm trong miền y tự động. |
label | string | Ghi ở đầu bên phải của đường (tự xuống dòng; biểu đồ chừa lề phải). |
goodSide | "below" | "above" | Phía nào là tốt. Khi có, mỗi tia có lần đo sẽ đếm chúng: "below" đếm các lần đo bằng hoặc dưới đường, "above" đếm các lần bằng hoặc trên đường. |
countLabel | string | Chữ sau số đếm, ví dụ "đúng giờ", "đạt". Mặc định là "below the line" hoặc "above the line". |
Từ ngữ: FountainLabels
| Trường | Mặc định | Hiện ở đâu |
|---|---|---|
usual | "usual" | Trước giá trị của chấm lớn: "usual 30". |
of | "of" | Giữa số đếm và tổng: "17 of 20". |
only | "only" | Trước một số lần đo ít: "only 5 days". |
forecast | "forecast" | Sau nhãn x của một tia dự báo và trong tooltip của nó: "Fri (forecast)". |
Biến giao diện
Biểu đồ đọc các biến CSS này từ phần tử chứa nó (hoặc một phần tử cha), với mọi trình vẽ:
| Biến | Mặc định | Tô màu cho |
|---|---|---|
--michi-vz-surface | #fff | Nền mà biểu đồ nằm trên: viền mảnh quanh mỗi chấm nhỏ và viền quanh chấm lớn, giúp tách chúng khỏi những gì nằm bên dưới. Với giao diện tối, hãy đặt nó bằng màu nền của trang. |
--michi-vz-attention | #c0392b | Các đường tham chiếu, nhãn của chúng và các số đếm dưới cột. |
--michi-vz-lake | #9cc3dd | Dải ở mức 0 (mặt hồ). |
--michi-vz-ink | currentColor | Đường xu hướng, dòng in đậm « usual 30 » và tiêu đề. |
--michi-vz-muted | #666 | Các nhãn giá trị khác, tiêu đề trục y, hướng dẫn đọc và nhãn trục. |
--michi-vz-grid | lightgray | Vạch mảnh phía trên hướng dẫn đọc. |
--michi-vz-font-family, --michi-vz-font-size | kế thừa, 12px | Mọi chữ mà biểu đồ in ra. |
Chấm lớn rỗng của một dự báo là một vòng tròn không tô gì bên trong (những gì nằm bên dưới bị cắt bỏ), nên nó vẫn rỗng trên mọi nền mà không cần biến nào.
/* Các biểu đồ trên một trang nền tối */
.dark .charts {
--michi-vz-surface: #1b1b1f;
--michi-vz-ink: #e3e3e3;
--michi-vz-muted: #a0a0a0;
}Sự kiện
Web component phát ra các CustomEvent nổi bọt (bubbling) sau đây (engine cũng cung cấp các sự kiện tương tự qua các callback on* trong bảng ở trên):
| Sự kiện | Chi tiết | Kích hoạt khi |
|---|---|---|
michi-vz:highlight | string[] | tia đang rê chuột thay đổi (nhãn của nó) |
michi-vz:colormapping | Record<string, string> | một ánh xạ màu được tạo ra |
michi-vz:dataprocessed | ChartContext | dữ liệu được xử lý (lại) |
michi-vz:datawarning | DataWarning[] | phát hiện cảnh báo về dữ liệu đầu vào (xem Cảnh báo) |
getContext()
mountFountainChart(el, props).getContext() trả về FountainChartContext không phụ thuộc renderer:
mode:"snapshot"khi trục x theo danh mục (band),"trend"khi trục x theo thời gian hoặc số.xAxis:{ type, domain }, là nhãn các cột ở chế độ ảnh chụp nhanh hoặc[min, max]ở chế độ xu hướng.yAxis:{ domain }.jets: mỗi tia đã vẽ một mục (theo thứ tự x ở chế độ xu hướng):
| Trường | Ý nghĩa |
|---|---|
label, code, color | Nhãn của tia, mã tùy chọn và màu cuối cùng. |
value | Chấm lớn. |
low, high | Đáy và đỉnh của đài phun; null nếu không có khoảng. |
range | high - low; null nếu không có khoảng. |
rangeRatio | range / |value|: khoảng lớn cỡ nào so với con số. null khi giá trị bằng 0 hoặc không có khoảng. |
sampleCount | Số chấm nhỏ. |
referenceCounts | Mỗi đường tham chiếu có goodSide một { value, goodSide, count, total, countLabel }; [] với tia dự báo hoặc tia không có lần đo. |
predicted | true với tia dự báo. |
xPosition | date gốc ở chế độ xu hướng, null ở chế độ ảnh chụp nhanh. |
spread | Đã lỗi thời: (high - low) / 2, 0 nếu không có khoảng. Dùng range. |
spreadRatio | Đã lỗi thời: spread / |value|, 0 nếu không tính được. Dùng rangeRatio. |
upperBound | Đã lỗi thời: high (hoặc giá trị nếu không có khoảng). Dùng high. |
lean | Đã lỗi thời: luôn là null. |
stats:jetCount: số tia đã vẽ.tallest:{ label, value }của giá trị lớn nhất, hoặcnull.widestRange:{ label, range }của khoảng rộng nhất, hoặcnullnếu không tia nào có khoảng.frothiest: đã lỗi thời.{ label, spreadRatio }của tia córangeRatiolớn nhất. DùngwidestRangehoặcjets[].rangeRatio.trendSlope: độ dốc (bình phương tối thiểu) của các giá trị theo kỳ (chế độ xu hướng, một chuỗi); ngược lại lànull.valueRange:[min, max]của các giá trị, hoặcnull.predictedCount: số tia dự báo.
legendData: mọi nhãn của toàn bộdataSetkèm màu, theo thứ tự xuất hiện; nhãn bị tắt vẫn giữ chỗ, đánh dấudisabled: true. Ở chế độ xu hướng chỉ có khi nhiều hơn một chuỗi.summary: một câu bằng lời đơn giản (tiếng Anh), ví dụFountain chart "How long is my commute, really?" with 4 jets. Highest usual value: Bus at 40. Widest range: Car, from 22 to 55.a11yTable: các cộtLabel,Usual, hai từendLabels,Samples, và mỗi đường tham chiếu cógoodSidemột cột (tiêu đề làcountLabel, ô dạng"17 of 20"); chế độ xu hướng thêmPeriodở đầu. Nhãn của tia dự báo có thêm "(forecast)" phía sau: hàng của nó ở chế độ xu hướng là["Year 4", "Battery (forecast)", …].
Xem ngữ cảnh LLM để biết cách dùng context trong prompt và báo cáo.
Cảnh báo
onDataWarning (và sự kiện michi-vz:datawarning) nhận DataWarning[], mỗi cảnh báo là { type, message, label? }. Biểu đồ không bao giờ lặng lẽ vẽ khác dữ liệu: mọi chỉnh sửa đều được báo.
type | Khi nào | Biểu đồ làm gì |
|---|---|---|
non-finite-value | Một mục không có value hữu hạn và không có lần đo, hoặc có lần đo không hữu hạn. | Bỏ qua tia (cũng không tính vào stats), hoặc bỏ các lần đo đó. Thiếu giá trị nhưng có lần đo thì dùng trung vị. |
range-excludes-value | low/high (hoặc spread) để giá trị nằm ngoài. | Nới rộng khoảng để chứa giá trị. |
sample-outside-range | Một lần đo nằm ngoài khoảng đã cho. | Nới rộng khoảng để chứa lần đo đó. |
inverted-range | low cao hơn high, hoặc spread âm. | Đổi chỗ hai đầu (dùng độ lớn của spread). |
missing-date | Chế độ xu hướng nhưng mục không có date dùng được. | Bỏ qua mục (biểu đồ vẫn ở chế độ xu hướng). |
duplicate-date | Hai tia cùng một ngày ở chế độ xu hướng. | Vẽ chồng lên nhau. |
duplicate-label | Một nhãn lặp lại ở chế độ ảnh chụp nhanh. | Các tia dùng chung một cột. |
out-of-domain | Một giá trị, một đầu khoảng hay một lần đo nằm ngoài yAxisDomain do bạn đặt, hoặc một đường tham chiếu nằm ngoài. | Giới hạn hình vẽ trong vùng biểu đồ; chấm nhỏ và đường nằm ngoài không được vẽ. |
ignored-option | Một prop đã bỏ được đặt, hoặc một mục có density hay lean. | Bỏ qua nó. |
empty-dataset | dataSet rỗng. | Hiện lớp phủ không có dữ liệu ("No data available", noDataLabel của bạn, hoặc lớp phủ riêng của bạn với suppressDefaultOverlay) thay cho trục và các mark. isNodata: false vẽ trục rỗng. |
layout-overflow | Mỗi tia có chưa tới 24 px, hoặc nhãn giá trị không vừa (cột hẹp, nhãn x phải xoay nghiêng, nhiều tia chung một cột, hoặc biểu đồ quá thấp). | Vẫn vẽ các tia và bỏ những nhãn giá trị không vừa, bỏ từ cho hai đầu trước. Hãy làm biểu đồ rộng hơn, bớt tia hoặc gộp lại. |
Lỗi thời
Tất cả những thứ sau vẫn chạy trong core 1.29 và sẽ bị xóa ở một phiên bản sau. Xem Chuyển từ core 1.28.
- Props, bị bỏ qua kèm cảnh báo
ignored-option:style,frothLayers,bloomExponent,stemFraction,showDroplets,showMist. Trên web component:fountainStyle(fountain-style). - Trường của mục:
predictedvàcertaintyvẫn được xử lý; hãy dùngforecast.densityvàleanbị bỏ qua kèm cảnh báo. - Trường của context:
jets[].spread,jets[].spreadRatio,jets[].upperBoundvàjets[].lean(luôn lànull);stats.frothiest. Hãy dùngrange,rangeRatio,highvàstats.widestRange.
Nguồn
Các props được định kiểu là FountainChartProps trong @michi-vz/core.
