Trực quan hoá dữ liệu
Một biểu đồ được người đọc và được máy thực thi: chọn dạng trước, gán màu theo nhiệm vụ, kiểm bảng màu bằng công cụ thay vì bằng mắt — rồi mới vẽ.
Chọn dạng biểu đồ
Màu đến sau cùng. Trước hết hỏi: người đọc cần làm gì với dữ liệu — so độ lớn, nhận diện chuỗi, thấy dấu âm/dương, hay chỉ cần một con số?
| Nhiệm vụ | Dạng mặc định | Việc của màu | Trong Yugen |
|---|---|---|---|
| Một giá trị hiện tại (+ xu hướng) | Ô số liệu — không phải biểu đồ một cột | — | StatTile |
| So sánh độ lớn | Cột; thanh ngang khi nhiều danh mục / tên dài | Một màu (ô 1) | BarChart |
| Xu hướng theo thời gian | Đường; vùng nếu chỉ một chuỗi | Một màu hoặc phân loại | LineChart AreaChart |
| Phân biệt nhiều chuỗi | Cột nhóm / chồng, nhiều đường | Phân loại | BarChart LineChart |
| Một chuỗi là trọng tâm | Nhấn mạnh: một màu, còn lại xám | 1 màu + xám | highlight |
| Trên / dưới mốc 0 | Cột phân kỳ | Phân kỳ (2 cực + giữa xám) | diverging |
| Phần – tổng | Cột chồng; donut ≤ 6 lát để nhìn nhanh | Phân loại | stacked DonutChart |
| Quan hệ giữa hai đại lượng | Phân tán; bong bóng khi có chiều thứ ba | Một màu; ≤ 3 nhóm phân loại | ScatterChart |
| Độ lớn trên lưới hai chiều (giờ × ngày, cohort) | Bản đồ nhiệt | Tuần tự; phân kỳ khi có mốc giữa | Heatmap |
| Hơn ~7 nhóm đều quan trọng | Bảng (hoặc bảng + biểu đồ) | — | Table |
Thang số chuỗi: 1–3 chuỗi chỉ màu là đủ; 4 chuỗi bắt buộc nhãn trực tiếp; 5–6 là trần mềm (legend hoặc small multiples); 7–8 là trần token. Chuỗi thứ 9 không bao giờ là một màu mới — gộp vào “Khác”, tách small multiples hoặc mã hoá kết hợp.
Câu trả lời là một con số
Câu chuyện là một chuỗi
Bảng màu & token
Mỗi màu làm đúng một việc: phân loại (nhận diện), tuần tự (độ lớn), phân kỳ (dấu), trạng thái (tốt/xấu — dành riêng). Bảng phân loại Yugen dẫn bằng Sakura, thứ tự cố định — chính thứ tự là cơ chế an toàn cho người mù màu.
Light · bề mặt #FFFFFF
- 1Sakura 桜#C2347A5.16:1
- 2Ai 藍 · chàm#2F6FD04.88:1
- 3Kohaku 琥珀 · hổ phách#B783003.35:1
- 4Fuji 藤 · tử đằng#7A5AD64.93:1
- 5Matcha 抹茶 · xanh ngọc#0E9F8A3.31:1
- 6Kaki 柿 · hồng giòn#D65A223.93:1
- 7Sora 空 · xanh trời#0A8FB83.73:1
- 8Koke 苔 · rêu#4E8A1E4.22:1
Dark · bề mặt #292929
- 1Sakura 桜#E24A923.90:1
- 2Ai 藍 · chàm#4A8EEB4.41:1
- 3Kohaku 琥珀 · hổ phách#C084004.53:1
- 4Fuji 藤 · tử đằng#9079E64.20:1
- 5Matcha 抹茶 · xanh ngọc#14A08A4.45:1
- 6Kaki 柿 · hồng giòn#E0662E4.23:1
- 7Sora 空 · xanh trời#22A4C64.98:1
- 8Koke 苔 · rêu#5FA0324.55:1
Dark không phải đảo màu tự động: cùng 8 sắc, mỗi sắc chọn bậc riêng cho bề mặt tối (OKLCH L 0.48–0.67) và kiểm lại trên #292929. Ở theme Tương phản cao mọi mark thành trắng; nhận diện chuyển sang hoa văn 45° / 135° (cột, lát) và nét đứt (đường).
| Kiểm tra (validate_palette.js) | Light · #FFFFFF | Dark · #292929 |
|---|---|---|
| Dải lightness OKLCH | PASS — cả 8 trong 0.43–0.77 | PASS — cả 8 trong 0.48–0.67 |
| Chroma ≥ 0.10 | PASS | PASS |
| Mù màu đỏ–lục, cặp kề (ΔE ≥ 8) | PASS — tệ nhất 12.9 (Kaki ↔ Matcha, deutan) | PASS — tệ nhất 12.8 (Kaki ↔ Matcha, protan) |
| Mắt thường, cặp kề (ΔE ≥ 15) | PASS — tệ nhất 19.8 (Koke ↔ Sora) | PASS — tệ nhất 19.0 (Koke ↔ Sora) |
| Tương phản với bề mặt ≥ 3:1 | PASS — 3.31 … 5.16 | PASS — 3.90 … 4.98 |
| Mọi cặp (scatter, bản đồ) | 3 màu đầu: ΔE 14.4 — trần 3 chuỗi | 3 màu đầu: ΔE 13.8 — trần 3 chuỗi |
# Từ thư mục skill dataviz — chạy cho từng chế độ, trên đúng bề mặt của biểu đồ
node scripts/validate_palette.js "#c2347a,#2f6fd0,#b78300,#7a5ad6,#0e9f8a,#d65a22,#0a8fb8,#4e8a1e" --mode light --surface "#ffffff"
node scripts/validate_palette.js "#e24a92,#4a8eeb,#c08400,#9079e6,#14a08a,#e0662e,#22a4c6,#5fa032" --mode dark --surface "#292929"
# Dạng "mọi cặp" (scatter, bản đồ, small multiples) — chỉ 3 màu đầu
node scripts/validate_palette.js "#c2347a,#2f6fd0,#b78300" --mode light --surface "#ffffff" --pairs allLight
Dark (neo đảo chiều)
Tuần tự là một sắc Sakura từ nhạt đến đậm (dark: neo đảo chiều — giá trị nhỏ chìm về nền). Khi dùng cho thứ bậc rời rạc (phễu, hạng) chỉ lấy bậc 3–7 để bậc nhạt nhất vẫn ≥ 2:1 (đã kiểm --ordinal). Phân kỳ: Sakura ↔ Ai, điểm giữa xám trung tính — không bao giờ là một sắc. Màu trạng thái (success / warning / danger) không nằm trong bảng phân loại và luôn đi cùng icon + chữ.
/* src/styles/charts.css — dùng trong SVG qua style={{ fill: "var(--…)" }} */
--colorChartCategorical1 … 8 /* nhận diện chuỗi, thứ tự cố định */
--colorChartSequential1 … 7 /* độ lớn, một sắc Sakura (ordinal: chỉ bậc 3–7) */
--colorChartDivergingNeg / Mid / Pos
--colorChartOther /* "Khác", chuỗi làm nền */
--colorChartSurface --colorChartGrid --colorChartAxis --colorChartCrosshair
--colorChartLabel --colorChartLabelStrong
--chartAreaOpacity --chartDimOpacityMark & khoảng trắng
Vẻ tĩnh, có chủ ý đến từ vài thông số cố định và hai khoảng trắng. Chỉ dữ liệu được phép “to tiếng”.
| Mark | Thông số |
|---|---|
| Cột / thanh | ≤ 24px (không lấp đầy khe), đầu dữ liệu bo 4px, vuông ở đường gốc, mọc từ một đường gốc |
| Đường | 2px, đầu và khớp bo tròn |
| Chấm / điểm cuối | ≥ 8px, cùng màu chuỗi, viền 2px màu bề mặt |
| Vùng | Màu chuỗi ~10% (dark 14%) — lớp nhạt, không phải khối đặc |
| Lưới / trục | Mảnh 1px, liền nét (không bao giờ đứt), lệch một bậc so với bề mặt |
| Khe bề mặt | 2px giữa mọi mark chạm nhau: đoạn cột chồng, cột cạnh nhau, lát donut — không vẽ viền quanh mark |
| Nhãn | Chọn lọc: điểm cuối, cực trị, chuỗi là trọng tâm. Chữ luôn dùng token chữ, không dùng màu chuỗi |
Tương tác
Biểu đồ HTML/SVG mặc định là tương tác. Tooltip bổ sung, không bao giờ là cách duy nhất để đọc giá trị.
- Đường / vùng: crosshair dọc bám mốc X gần nhất; một tooltip liệt kê mọi chuỗi tại mốc đó.
- Cột / lát: chính mark là vùng chạm (rộng hơn mark, gồm cả khe); mark được chọn nổi lên, các mark khác mờ đi.
- Trong tooltip giá trị đậm và đứng trước về thứ bậc; tên chuỗi là phụ, khoá bằng một nét ngắn màu chuỗi (không phải ô đặc). Legend thì phản chiếu mark: ô cho cột / vùng, nét cho đường.
- Legend của biểu đồ nhiều chuỗi là nút bật/tắt; chuỗi còn lại giữ nguyên màu (màu theo thực thể, không theo thứ hạng).
- Bộ lọc (khoảng ngày, chiều dữ liệu) nằm một hàng phía trên mọi biểu đồ mà nó tác động — không đặt trong thẻ biểu đồ.
| Phím | Hành vi |
|---|---|
| Tab | Vào biểu đồ (một điểm dừng duy nhất) — tooltip hiện cho điểm đang focus. |
| ←→↑↓ | Điểm trước / sau (vùng vẽ luôn LTR nên → là tiến, kể cả trang RTL). |
| HomeEnd | Điểm đầu / cuối. |
| Esc | Ẩn tooltip. |
Khả năng tiếp cận
Nhận diện không bao giờ chỉ dựa vào màu: legend luôn có khi ≥ 2 chuỗi, nhãn trực tiếp khi ≤ 4, và mọi biểu đồ có bảng dữ liệu tương đương.
- Khung là
figurecó tên từ tiêu đề; vùng vẽ SVG mangaria-labeltóm tắt dữ liệu; mỗi điểm dữ liệu focus được làrole="img"với nhãn “danh mục, chuỗi: giá trị”. - Nút Bảng dữ liệu chuyển sang
tablecó tiêu đề cột và tiêu đề hàng — bản tương đương đạt WCAG của biểu đồ. - Theme Tương phản cao và
forced-colorstự bật hoa văn / nét đứt; proptexturebật thủ công (in ấn, mù màu toàn phần). - Số và ngày định dạng bằng Intl theo
locale(mặc định vi-VN): trục rút gọn 1 N / 2,5 Tr, tooltip và bảng đầy đủ. - Vùng vẽ luôn
dir="ltr"(trục thời gian không đảo); tiêu đề, legend và tooltip theo hướng chữ của trang. - Animation vào cảnh (cột mọc từ gốc, đường tự vẽ) tắt hẳn khi
prefers-reduced-motion.
| Tháng | Trực tuyến | Cửa hàng |
|---|---|---|
| T7 | 510 | 325 |
| T8 | 488 | 340 |
| T9 | 560 | 352 |
| T10 | 615 | 360 |
Lỗi thường gặp
Nếu biểu đồ khớp một mục bên phải, nó sai — sửa trước khi phát hành.
- Hai đại lượng khác thang → hai biểu đồ, small multiples, hoặc chỉ số hoá về cùng gốc trên một trục.
- Màu theo thực thể: lọc bớt chuỗi thì chuỗi còn lại giữ nguyên màu.
- Câu chuyện là một con số → StatTile; là một chuỗi → highlight, phần còn lại xám.
- Lưới và trục mảnh 1px liền nét, lùi về sau; cột mảnh, nhiều khoảng thở.
- Nhãn không vừa trong mark thì đưa ra ngoài đầu cột hoặc vào tooltip — giá trị vẫn có trong bảng.
- Chạy validate_palette.js cho mọi bảng màu mới, cả light và dark.
- Biểu đồ hai trục Y — tạo ra tương quan không có thật.
- Sinh thêm màu thứ 9, hoặc xoay vòng màu khi quá 8 chuỗi.
- Cầu vồng cho dữ liệu tuần tự; một sắc ở điểm giữa phân kỳ; hai cực cùng tông lạnh.
- Màu trạng thái dùng cho “chuỗi 4”, hoặc màu chuỗi dùng để báo trạng thái.
- Donut để so các giá trị sát nhau, pie 2 lát, biểu đồ một cột.
- Ghi số ở mọi điểm, lưới nét đứt, viền vẽ quanh mark, tooltip là cách duy nhất để đọc giá trị.