API Biểu đồ đường
Mọi thứ bạn cần để tích hợp biểu đồ đường bằng code; để xem câu chuyện và bản demo, xem bản demo Biểu đồ đường.
Import
import "@michi-vz/wc/line-chart";
// <michi-vz-line-chart> is now definedimport { mountLineChart } from "@michi-vz/core";
const chart = mountLineChart(el, props);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. |
dataSet* | LineDataItem[] | - | Array of line series, each with its own points |
title | string | - | Optional chart title rendered above the plot |
yAxisDomain | [number, number] | - | Fix the y-axis range as [min, max] instead of deriving it from the data |
yAxisScale | "linear" | "log" | "linear" | Y-axis scale: "linear" (default) or a base-10 "log" scale. In "log" mode, a non-positive value (<= 0) can't be plotted, so those points are dropped as missing (reported via `onDataWarning`); a dataSet with no positive values at all renders the no-data state instead. |
xAxisDataType | "date_annual" | "date_monthly" | "number" | "number" | How x values are parsed and formatted: yearly dates, monthly dates, or plain numbers |
xAxisFormat | (d: number | string) => string | - | Formats an x tick value into its display label |
yAxisFormat | (d: number | string) => string | - | Formats a y tick value into its display label |
ticks | number | 5 | Approximate number of x-axis ticks to generate |
yTicks | number | - | Number of y-axis ticks (default 10, matching the legacy denser value axis). |
showGridLines | boolean | - | Draw horizontal dashed grid lines at each y tick (default true). |
showVerticalGridLines | boolean | - | Draw vertical dashed grid lines at each x tick (default false - the legacy chart drew none). |
highlightZeroLine | boolean | - | Emphasise the y=0 grid line with a darker solid stroke (default true). |
tickValues | Array<number | Date> | - | Explicit tick values, overriding the generated ones |
fillPeriodTicks | boolean | - | Draw a tick for EVERY period across the axis range (every month/year), not just the periods present in the data. Periods with no value render faded and show `noDataTickTooltip` on hover. Opt-in; default false. |
noDataTickTooltip | (date: number) => string | - | Tooltip content (plain text or sanitized HTML) for a faded no-data tick; receives the tick's epoch-ms value. Used only with `fillPeriodTicks`. Default: a localized "Data not available". |
noDataTickColor | string | - | Colour for faded no-data tick labels; sets the `--michi-vz-tick-nodata` CSS var on the host. Used only with `fillPeriodTicks`. |
curve | "curveBumpX" | "curveLinear" | "curveMonotoneX" | - | Default interpolation for every series (per-series `curve` wins). |
detectGaps | boolean | false | Auto-derive `certainty` from missing periods (dashes the gap segment). |
expectedStep | number | - | Expected cadence in axis units; REQUIRED for xAxisDataType "number". |
showDataPoints | boolean | false | Whether to draw a marker at each data point (default false) |
enableMouseLine | boolean | MouseLineConfig | true | Solid vertical crosshair line snapped to the nearest data point x on hover; pass a config object to style it (default true) |
singlePointLine | boolean | SinglePointLineConfig | - | true / config draws a horizontal guide line for single-point series. |
fontFamily | string | - | Font family for axis/title/tooltip text (SVG + canvas). Sets the --michi-vz-font-family CSS var so both renderers resolve it. |
filter | Filter | - | Top-N / sort filter applied to the data before rendering |
progressiveDraw | boolean | ProgressiveDrawConfig | - | Animate each line drawing itself left to right on mount (progressive reveal). `true` uses defaults; pass a config to tune duration, easing, tip labels, and autoplay. Off by default, so existing charts are unchanged. Respects prefers-reduced-motion: the chart then renders fully drawn instantly. Ignored by the webgpu renderer. |
isLoading | boolean | - | Show the loading overlay and skip the no-data check (legacy michi-vz parity). |
isNodata | | boolean | ((dataSet: LineDataItem[] | null | undefined) => boolean) | - | No-data override: boolean, or a predicate on dataSet; default = empty/all-empty-series. |
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. |
tooltipFormatter | ( d: DataPoint, series: DataPoint[], dataSet: LineDataItem[], ) => string | - | Returns custom tooltip HTML for a hovered datum (sanitized before it is inserted) |
sharedTooltip | boolean | false | When true, hovering anywhere in the plot shows ONE tooltip listing every series' value at the nearest x (year) - the "shared"/crosshair tooltip - instead of the single nearest series. Pairs with the crosshair (enableMouseLine, on by default). |
sharedTooltipFormatter | (input: { x: number | string; xLabel: string; entries: Array<{ label: string; value: number; color: string; d: DataPoint }>; }) => string | - | Custom HTML for the shared tooltip. `entries` is one row per series that has a point at the hovered x, in dataSet order, each with its resolved colour. |
onHighlightItem | (labels: string[]) => void | - | Called when the hovered/highlighted label(s) change |
svgChildren | string | - | Pre-serialised SVG markup injected as direct <svg> children (axis-title text, reference lines). The React wrapper fills this from `children`; mirrors the legacy <LineChart>'s `{children}` slot. |
Common props - shared by every chart (14)
| Prop | Type | Default | Description |
|---|---|---|---|
width | number | 1000 | Chart width in pixels |
height | number | 500 | Chart height in pixels |
margin | Margin | { top: 50, right: 50, bottom: 50, left: 60 } | Inner margins (top/right/bottom/left, in px) reserved for axes, titles, and labels |
colors | string[] | - | Categorical palette for series/labels 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; all other marks dim |
disabledItems | string[] | - | Labels to hide and exclude from scales/stacks |
renderer | "svg" | "canvas" | "webgpu" | "svg" | Render as inline SVG (default) or to a canvas (faster for large datasets); getContext() is identical either way |
locale | string | - | BCP-47 locale used for number and date formatting |
skipColorMappingDispatch | boolean | false | External-CSS mode: unmapped labels resolve to transparent and onColorMappingGenerated is not emitted, so mark colours come from your CSS via the data-label-safe contract |
enableTransitions | boolean | true | Animate updates with CSS transitions (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 (duplicate labels, non-finite values, non-monotonic dates, ...) |
Hiển thị lưới và trục
Bốn prop kiểm soát mật độ vạch chia trục y và cách vẽ đường lưới:
| Prop | Mặc định | Ghi chú |
|---|---|---|
yTicks | 10 | Số lượng vạch chia trục y gần đúng. Giá trị mặc định kế thừa là 10; đặt thấp hơn (ví dụ 5) để trục thưa hơn. |
showGridLines | true | Các đường lưới nét đứt ngang tại mỗi vạch chia y. |
showVerticalGridLines | false | Các đường lưới nét đứt dọc tại mỗi vạch chia x. Biểu đồ phiên bản cũ không vẽ đường nào; chỉ bật khi các đường dẫn hướng thêm giúp dễ đọc hơn. |
highlightZeroLine | true | Vẽ đường y=0 dưới dạng nét liền (tô màu bằng --michi-vz-zero-line, mặc định lấy theo màu lưới) thay vì một vạch chia nét đứt thông thường. Hữu ích khi tập dữ liệu trải cả giá trị dương lẫn âm. |
Trạng thái đang tải và không có dữ liệu
Engine quản lý một thuộc tính data-mv-state trên phần tử host với ba giá trị - "loading", "nodata", và "ready" - và hiển thị các lớp phủ dựng sẵn cho hai trạng thái đầu trừ khi bạn tắt đi.
| Prop | Kiểu | Mặc định | Ghi chú |
|---|---|---|---|
isLoading | boolean | false | Hiển thị lớp phủ .mv-loading và bỏ qua hoàn toàn việc kiểm tra không có dữ liệu. |
isNodata | boolean | (dataSet) => boolean | - | Ghi đè điều kiện mặc định (dataSet rỗng hoặc mọi chuỗi đều không có điểm nào). Truyền false để buộc biểu đồ vẫn hiển thị ngay cả khi dữ liệu trông như trống. |
noDataLabel | string | - | Văn bản hiển thị bên trong lớp phủ .mv-nodata mặc định. Bị bỏ qua khi suppressDefaultOverlay là true. |
suppressDefaultOverlay | boolean | false | Ngăn engine tự chèn node đang tải/không có dữ liệu của riêng nó. Dùng khi một wrapper framework (ví dụ LineChart của @michi-vz/react) render isLoadingComponent / isNodataComponent như một lớp phủ React thay thế. Host không bao giờ bị unmount - lớp phủ chỉ được xếp chồng lên trên. |
Hành vi của wrapper React
LineChart của @michi-vz/react tự động đặt suppressDefaultOverlay và render isLoadingComponent / isNodataComponent như một node React được định vị phía trên host của biểu đồ. DOM của biểu đồ luôn được mount, vì vậy isNodataComponent vẫn kích hoạt khi dữ liệu trống ngay cả khi không có điều kiện tùy chỉnh.
Font chữ
fontFamily đặt custom property CSS --michi-vz-font-family trên phần tử host, được cả bộ dựng văn bản SVG lẫn probe getComputedStyle của canvas đọc. Font phải đã được trang tải sẵn - không có việc nhúng font nào được thực hiện.
ChartContext / legendData
onChartDataProcessed nhận một LineChartContext mở rộng từ BaseChartContext. Lớp cơ sở giờ đây mang thêm một trường legendData:
interface LegendItem {
label: string; // series label as it appears in dataSet
color: string; // resolved colour at the time of processing
order: number; // appearance order (legend slot index)
disabled?: boolean; // true when the label is currently hidden
dataLabelSafe?: string; // sanitizeForClassName(label) - the CSS hook the canvas colour probe matches
}
interface BaseChartContext {
// ... existing fields ...
legendData?: LegendItem[]; // populated by LineChart; treat absence as []
}legendData là payload chuẩn dành cho các bên chịu trách nhiệm về màu sắc phía consumer. Một wrapper framework tự quản lý CSS màu của riêng nó (ví dụ useChartUtils của thd MonitorV2) đọc legendData[].{label, dataLabelSafe, color, disabled} từ mỗi lần gọi onChartDataProcessed và phát ra các quy tắc stroke/fill theo từng nhãn, nhắm vào thuộc tính data-label-safe. Điều này thay thế nhu cầu phải đối chiếu chéo colorsMapping với thứ tự chuỗi.
Events
Web component phát ra các CustomEvent nổi bọt (bubbling) sau đây (engine cũng cung cấp tương đương qua các callback on* trong bảng ở trên):
| Event | Detail | Kích hoạt khi |
|---|---|---|
michi-vz:highlight | string[] | khi trạng thái tô sáng hover thay đổi |
michi-vz:colormapping | Record<string, string> | khi một color mapping được tạo ra |
michi-vz:dataprocessed | ChartContext | khi dữ liệu được xử lý (lại) |
michi-vz:datawarning | DataWarning[] | khi phát hiện cảnh báo về dữ liệu đầu vào |
getContext()
mountLineChart(el, props).getContext() trả về một LineChartContext không phụ thuộc bộ dựng (renderer-agnostic) (số liệu thống kê có cấu trúc + một bản tóm tắt ngôn ngữ tự nhiên có tính xác định + một bảng a11y). Xem ngữ cảnh LLM.
Source
Các prop được định kiểu là LineChartProps trong @michi-vz/core.
