Skip to content

Biểu đồ cột chồng dọc

Cơ cấu

"Mỗi danh mục được cấu thành từ gì, và cơ cấu đó thay đổi ra sao qua các danh mục?" Xếp chồng các phần trong một cột cho mỗi danh mục, và cơ cấu hiện ra chỉ trong nháy mắt. Khi một đoạn bị thiếu, một cơ chế bảo vệ tường minh đánh dấu khoảng trống đó thay vì âm thầm làm phẳng nó về 0.

Example
canvas · responsive
Tìm hiểu thêm: Hướng dẫn Insights·Hướng dẫn DevTools

Cần so sánh hai thứ cạnh nhau? Truyền nhiều hơn một chuỗi trong dataSet và các cột sẽ gộp nhóm: mỗi danh mục trục x, bạn có một cột chồng cho mỗi chuỗi, được xếp cạnh nhau. Ở đây, hai khu vực qua ba năm, mỗi cột chia thành năm dòng sản phẩm - để bạn đọc được khu vực nào lớn hơn cơ cấu của nó khác nhau ra sao, cùng một lúc:

Example
canvas · responsive
Tìm hiểu thêm: Hướng dẫn Insights·Hướng dẫn DevTools

Biểu đồ ở trên là cùng một engine trên mọi framework - chỉ có mã tích hợp bên dưới là khác nhau.

Dữ liệu lớn trên WebGPU Thử nghiệm

VerticalStackBarChart có renderer="webgpu" tùy chọn, vẽ các cột của nó trên GPU trong khi trục, nhãn và tooltip vẫn nằm trên lớp SVG. Tính năng này được kiểm soát theo khả năng phần cứng: trên trình duyệt không có WebGPU, nó tự động hạ cấp về canvas, và getContext().renderer báo cáo bộ dựng thực sự đã vẽ.

⚗️ 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 · ~150 cột × 5 khóa… detecting

Hiệu ứng vẽ dần

Biểu đồ tự vẽ dần từ trái sang phải ngay khi mount, hiện lần lượt các nét vẽ trước khi ổn định vào vị trí. Mặc định tắt - không bật thì biểu đồ giữ nguyên như cũ.

Mỗi đường lớn dần từ năm đầu đến năm cuối; nhãn bám theo ngọn đường rồi dừng ở điểm cuối. Khi hệ điều hành bật reduced motion, biểu đồ hiển thị đầy đủ ngay lập tức.

progressiveDraw: true dùng cấu hình mặc định (1200 ms, easeInOutCubic). Truyền object để tinh chỉnh:

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

<VerticalStackBarChart
  ref={ref}
  {...props}
  progressiveDraw={{ durationMs: 2000 }}
/>;
// ref.current?.replay() chạy lại hiệu ứng khi cần
vue
<VerticalStackBarChart :options="{ ...props, progressiveDraw: { durationMs: 2000 } }" />
svelte
<div use:verticalStackBarChart={{ ...props, progressiveDraw: { durationMs: 2000 } }}></div>
ts
applyVerticalStackBarChartProps(this.c.nativeElement, {
  ...props,
  progressiveDraw: { durationMs: 2000 },
});
html
<michi-vz-vertical-stack-bar-chart id="c"></michi-vz-vertical-stack-bar-chart>
<script>
  const el = document.getElementById("c");
  el.progressiveDraw = { durationMs: 2000 };
  // el.replay() chạy lại hiệu ứng
</script>
  • durationMseasing ("linear", "easeOutQuad", "easeInOutCubic", hoặc hàm (t) => t tự viết) quyết định nhịp vẽ.
  • autoplay: false hiển thị biểu đồ vẽ sẵn đầy đủ; gọi replay() (ref handle bên React, method của web component, hoặc instance của core) để chạy hiệu ứng khi cần. replayOnUpdate: true chạy lại mỗi lần dữ liệu thay đổi.
  • Tôn trọng prefers-reduced-motion: biểu đồ hiển thị đầy đủ ngay, không animation.

Xem dữ liệu chạy theo năm

Dữ liệu vốn đã trải dài qua nhiều năm nên không cần gắn thêm gì cả. Bật timeline: nút play và thanh tua riêng của biểu đồ chạy qua các năm đó, mỗi bước từng cột chồng chỉ vẽ đến năm đang active rồi khi chạy tiếp sẽ nối dài mượt mà thêm ra. Kéo lùi thanh tua thì cột cũng co lại tương ứng. Hover chỉ soi được phần đã thực sự vẽ ra. Mặc định tắt - không bật thì biểu đồ giữ nguyên.

Bấm nút play dưới biểu đồ: biểu đồ vẽ dần đến từng năm khi chạy qua. Kéo thanh tua để nhảy đến năm bất kỳ.

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

<VerticalStackBarChart ref={ref} {...props} timeline={{ speedMs: 1000, loop: true }} />;
// ref.current?.timeline() -> play() / pause() / seek(year) / stepForward()
vue
<VerticalStackBarChart :options="{ ...props, timeline: { speedMs: 1000, loop: true } }" />
svelte
<div use:verticalStackBarChart={{ ...props, timeline: { speedMs: 1000, loop: true } }}></div>
ts
applyVerticalStackBarChartProps(this.c.nativeElement, { ...props, timeline: { speedMs: 1000, loop: true } });
html
<michi-vz-vertical-stack-bar-chart id="c"></michi-vz-vertical-stack-bar-chart>
<script>
  const el = document.getElementById("c");
  el.timeline = { speedMs: 1000, loop: true };
  // el.getTimeline() -> play() / pause() / seek(year)
</script>
  • speedMs chỉnh nhịp chạy, loop quay vòng, autoplay: true tự chạy khi mount, showControl: false ẩn thanh điều khiển có sẵn.
  • Controller headless luôn sẵn sàng: chart.timeline() cho play() / pause() / toggle() / seek(period) / stepForward() / stepBack(), kèm onStepformatPeriod trong config khi cần tự dựng UI.
  • Giá trị trượt mượt giữa các năm theo mặc định (interpolate); đặt interpolate: false để cắt thẳng. Khi bật reduced motion, biểu đồ luôn cắt thẳng.
  • timeline được ưu tiên hơn progressiveDraw khi cả hai cùng được bật trên một biểu đồ.

Cách dùng

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

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

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

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

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

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

API

Các prop được định kiểu là VerticalStackBarChartProps trong @michi-vz/core. Dùng chung cho mọi biểu đồ: width, height, margin, colors / colorsMapping, renderer ("svg", "canvas", hoặc "webgpu" thử nghiệm), highlightItems, disabledItems, và các callback on*. onChartDataProcessed / getContext() trả về ChartContext không phụ thuộc bộ dựng.

Ghi chú hành vi

Các hành vi này là tự động (không cần cấu hình thêm) và khớp với biểu đồ michi-vz cũ để tương đồng khi thay thế trực tiếp.

Trục x dày đặc - tự động xoay / thu gọn

Trục dạng dải đo các nhãn của nó và tự thích ứng: nằm ngang khi vừa đủ chỗ, xoay −45° (vẫn hiển thị tất cả nhãn) khi không vừa, và thu gọn về một tập con cách đều nhau chỉ khi mật độ quá cao. Lề dưới được dành sẵn tự động để các nhãn xoay không bao giờ bị cắt. Không cần prop nào - truyền xAxisFormat để định dạng văn bản mốc (ví dụ 20240101-2024).

date chấp nhận số

date của một hàng có thể là một number (ví dụ date: 2024) hoặc một chuỗi; engine sẽ ép kiểu bằng String(). Thang dải là scaleBand<string>, nên các kiểu hỗn hợp được chuẩn hóa nhất quán.

keysOrder và thứ tự màu

keysOrder ("topToBottom" mặc định | "bottomToTop") chọn đầu nào của chồng cột keys[0] sẽ nằm. Với "bottomToTop", thứ tự chú giải / màu bị đảo ngược so với thứ tự vẽ chồng - do đó một thành phần quản lý màu của consumer gán màu theo thứ tự xuất hiện trong legendData sẽ gắn khóa vị trí 0 với khóa trên cùng, chứ không phải khóa dưới cùng. Thứ tự vẽ chồng (pixel) được quyết định độc lập và không bị ảnh hưởng.

filter - nhóm Top/Bottom-N

filter = { limit, sortingDir } xếp hạng các DataSet (nhóm) theo tổng lớn của chúng trên tất cả các hàng + khóa và giữ lại limit nhóm đứng đầu ("desc") hoặc cuối ("asc"). Mọi thứ phía sau (khóa, ngày, miền y, cột và chú giải) đều bắt nguồn từ tập đã lọc, nên chú giải luôn phản ánh chính xác các cột được vẽ.

disabledItems

Các tên trong disabledItems loại bỏ cả khóa đoạn khớp lẫn nhóm DataSet. Vô hiệu hóa một nhóm khiến các cột còn lại rộng ra để chia đều dải giữa các nhóm còn hiển thị.

tooltipFormatter

Nhận { item, key, seriesKey, series, isMissing } - item là toàn bộ hàng dữ liệu, key là đoạn đang được trỏ chuột vào, series là các hàng của đoạn đó qua các ngày. Tooltip có sẵn nhận biết mép biên: nó lật sang bên trái con trỏ khi gần mép phải và tụt xuống dưới con trỏ khi gần mép trên, nên không bao giờ tràn ra ngoài màn hình.

Tương tác (canvas)

Di chuột vào một đoạn làm mờ các đoạn khác ngay trong cùng khung hình (không có độ trễ đầu vào); rời khỏi biểu đồ sẽ xóa hiệu ứng mờ. Nhấp vào một cột để ghim tooltip, nhấp lại để ghim lại, và nhấp ra ngoài biểu đồ để bỏ ghim.