data-viz-2025

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Data Visualization 2025: The Art & Science of Visual Communication

2025数据可视化:视觉传达的艺术与科学

Create visualizations that Seaborn users, Tufte readers, and everyone else will love. Marry NYT Graphics rigor with MoMA aesthetics, Nike energy, and On Kawara precision.
打造Seaborn用户、Tufte读者及所有用户都喜爱的可视化作品。将《纽约时报》图形团队的严谨性与MoMA的美学、Nike的活力及On Kawara的精准度相结合。

When to Use This Skill

何时使用该技能

Use for:
  • Building interactive charts, dashboards, and data stories
  • Complex visualizations (chord diagrams, Sankey flows, network graphs)
  • Real-time data displays with animations
  • Mobile-responsive data components
  • Accessible, tested visualizations for production
NOT for:
  • Static PNG/SVG exports without interaction (use design tools)
  • Basic HTML tables (use semantic markup)
  • Print-only graphics (different constraints)
  • Simple icon displays (use icon libraries)
适用场景:
  • 构建交互式图表、仪表盘和数据故事
  • 复杂可视化(弦图、桑基流图、网络图)
  • 带动画的实时数据展示
  • 移动端响应式数据组件
  • 用于生产环境、经过测试且无障碍的可视化内容
不适用场景:
  • 无交互的静态PNG/SVG导出(使用设计工具)
  • 基础HTML表格(使用语义化标记)
  • 仅用于印刷的图形(约束条件不同)
  • 简单图标展示(使用图标库)

Core Philosophy: The Three Pillars

核心理念:三大支柱

1. Clarity (Tufte's Data-Ink Ratio)

1. 清晰性(Tufte的数据墨水比原则)

Every visual element must earn its place. Remove chart junk, maximize signal-to-noise.
每个视觉元素都必须有存在的意义。移除图表冗余,最大化信号噪声比。

2. Beauty (Aesthetic Standards)

2. 美观性(美学标准)

Visualizations are art. Use spring physics, thoughtful color, and premium design systems.
可视化是艺术。使用弹簧物理动效、精心搭配的色彩和优质设计系统。

3. Truth (Graphical Integrity)

3. 真实性(图形完整性)

Data representation must be honest. Test rigorously, document assumptions, preserve context.
数据呈现必须真实。严格测试、记录假设、保留上下文。

Quick Decision Tree

快速决策树

What are you building?
├─ Exploratory analysis / many iterations
│  └─ → Observable Plot (grammar-of-graphics)
├─ Standard business charts (bars, lines, pies)
│  ├─ Simple React integration needed
│  │  └─ → Recharts (easiest, most popular)
│  └─ Premium aesthetics + theming
│     └─ → Nivo (beautiful out of the box)
├─ Custom, one-of-a-kind visualizations
│  ├─ Need low-level control
│  │  └─ → Visx (React + D3 primitives)
│  └─ Full D3 power
│     └─ → D3.js directly (steeper learning curve)
└─ Dashboard with Tailwind design system
   ├─ → Tremor (purpose-built for dashboards)
   └─ → shadcn-ui Charts (Recharts + shadcn styling)
你要构建什么?
├─ 探索性分析 / 多轮迭代
│  └─ → Observable Plot(图形语法)
├─ 标准业务图表(柱状图、折线图、饼图)
│  ├─ 需要简单的React集成
│  │  └─ → Recharts(最简单、最流行)
│  └─ 高级美学 + 主题定制
│     └─ → Nivo(开箱即美)
├─ 自定义、独一无二的可视化
│  ├─ 需要底层控制
│  │  └─ → Visx(React + D3原语)
│  └─ 完整D3能力
│     └─ → D3.js直接使用(学习曲线较陡)
└─ 基于Tailwind设计系统的仪表盘
   ├─ → Tremor(专为仪表盘打造)
   └─ → shadcn-ui Charts(Recharts + shadcn样式)

The Data Viz Stack (2025)

2025年数据可视化技术栈

Recommended Packages

推荐包

json
{
  "dependencies": {
    "@observablehq/plot": "^0.6.0",        // Exploratory, grammar-of-graphics
    "recharts": "^2.12.0",                  // React charts, simple & popular
    "@nivo/core": "^0.87.0",                // Beautiful, themeable charts
    "@visx/visx": "^3.10.0",                // Low-level D3 + React primitives
    "d3": "^7.9.0",                         // Direct D3 for custom work
    "@tremor/react": "^3.15.0",             // Tailwind dashboard components
    "framer-motion": "^11.0.0"              // Smooth animations
  },
  "devDependencies": {
    "@percy/cli": "^1.29.0",                // Visual regression testing
    "@testing-library/react": "^14.2.0",    // Component testing
    "@storybook/react": "^7.6.0"            // Component playground
  }
}
json
{
  "dependencies": {
    "@observablehq/plot": "^0.6.0",        // 探索性分析、图形语法
    "recharts": "^2.12.0",                  // React图表,简单易用且流行
    "@nivo/core": "^0.87.0",                // 美观、支持主题定制的图表
    "@visx/visx": "^3.10.0",                // 底层D3 + React原语
    "d3": "^7.9.0",                         // 直接使用D3进行自定义开发
    "@tremor/react": "^3.15.0",             // Tailwind仪表盘组件
    "framer-motion": "^11.0.0"              // 流畅动画
  },
  "devDependencies": {
    "@percy/cli": "^1.29.0",                // 视觉回归测试
    "@testing-library/react": "^14.2.0",    // 组件测试
    "@storybook/react": "^7.6.0"            // 组件演示平台
  }
}

When to Use Each Library

各库的适用场景

Observable Plot - You want ggplot2/Vega-Lite in JavaScript
  • Grammar-of-graphics approach (marks, scales, transforms)
  • Perfect for rapid prototyping
  • Great for notebooks and exploratory analysis
Recharts - You want it to "just work" in React
  • Component-based (everything is a
    <Component />
    )
  • Excellent documentation and community
  • TypeScript support built-in
  • Smallest learning curve
Nivo - You want visually stunning results
  • 20+ chart types with beautiful defaults
  • Canvas, SVG, and HTML rendering
  • Server-side rendering support (unique feature)
  • Extensive customization via props
Visx - You want maximum control with React patterns
  • Low-level primitives (scales, axes, shapes)
  • Compose your own chart types
  • Airbnb's D3 + React toolkit
  • Best for novel visualizations
D3.js - You want unlimited power (and responsibility)
  • Full control over every pixel
  • Steepest learning curve
  • Best for advanced, custom work
  • Use with
    useEffect
    and
    useRef
    in React
Observable Plot - 你想在JavaScript中使用ggplot2/Vega-Lite风格
  • 图形语法方法(标记、比例尺、转换)
  • 非常适合快速原型开发
  • 适用于笔记本和探索性分析
Recharts - 你想在React中“开箱即用”
  • 基于组件的设计(所有内容都是
    <Component />
  • 优秀的文档和社区支持
  • 内置TypeScript支持
  • 学习曲线最平缓
Nivo - 你想获得视觉惊艳的结果
  • 20+种图表类型,默认样式美观
  • 支持Canvas、SVG和HTML渲染
  • 独特特性:支持服务端渲染
  • 通过props实现广泛定制
Visx - 你想通过React模式获得最大控制权
  • 底层原语(比例尺、坐标轴、形状)
  • 组合自定义图表类型
  • Airbnb的D3 + React工具包
  • 最适合创新型可视化
D3.js - 你想要无限能力(也需承担相应责任)
  • 完全控制每个像素
  • 学习曲线最陡峭
  • 最适合高级自定义开发
  • 在React中结合
    useEffect
    useRef
    使用

The Tufte Checklist

Tufte检查清单

Before shipping any visualization, verify:
  • Data-ink ratio maximized - Remove gridlines, decorations, 3D effects, shadows
  • Graphical integrity - Visual representation proportional to data values
  • Clear labeling - Direct labels on data (not legends requiring color matching)
  • No chart junk - No unnecessary ornamentation or Moiré vibration
  • Layered information - Use small multiples instead of overloaded single charts
  • Show data variation, not design variation - Consistent visual encoding
Read
references/tufte-principles.md
for deep dive.
发布任何可视化内容前,请验证:
  • 最大化数据墨水比 - 移除网格线、装饰、3D效果、阴影
  • 图形完整性 - 视觉呈现与数据值成比例
  • 清晰标注 - 在数据上直接标注(而非需要颜色匹配的图例)
  • 无图表冗余 - 无不必要的装饰或莫尔条纹
  • 分层信息 - 使用小多图而非过度拥挤的单一图表
  • 展示数据变化,而非设计变化 - 保持视觉编码一致
深入了解请阅读
references/tufte-principles.md

The NYT Graphics Workflow

《纽约时报》图形团队工作流

The New York Times graphics team process:
  1. Make 500 charts → Pick the one that displays information best
  2. Simplify within reason → Remove noise and clutter
  3. Annotate with insight → Words should highlight patterns, not just describe data
  4. Test with real users → Watch people interact, identify confusion
  5. Responsive by default → Mobile-first, progressive enhancement
Read
references/nyt-workflow.md
for case studies.
《纽约时报》图形团队的流程:
  1. 制作500张图表 → 选择最能清晰展示信息的那一张
  2. 合理简化 → 移除噪声和杂乱元素
  3. 用洞察注释 → 文字应突出模式,而非仅描述数据
  4. 真实用户测试 → 观察用户交互,识别困惑点
  5. 默认响应式 → 移动端优先,渐进式增强
案例研究请阅读
references/nyt-workflow.md

Animation & Micro-interactions

动画与微交互

Data viz isn't static. Movement communicates:
数据可视化不是静态的。动效可以传递信息:

When to Animate

何时使用动画

  • State transitions - Data updates, filter changes
  • Draw attention - Highlight insights, guide the eye
  • Show relationships - Morphing between views reveals structure
  • Delight - Thoughtful motion = premium feel
  • 状态转换 - 数据更新、筛选条件变化
  • 吸引注意力 - 突出洞察、引导视线
  • 展示关系 - 视图间的变形揭示结构
  • 愉悦体验 - 精心设计的动效带来高级感

Animation Principles

动画原则

typescript
// Use spring physics, not linear easing
const springConfig = {
  type: "spring",
  stiffness: 300,
  damping: 30
};

// Stagger for multiple elements
const staggerChildren = {
  delayChildren: 0.1,
  staggerChildren: 0.05
};

// Respect prefers-reduced-motion
const shouldAnimate = !window.matchMedia('(prefers-reduced-motion: reduce)').matches;
Read
references/animation-patterns.md
for complete patterns library.
typescript
// 使用弹簧物理动效,而非线性缓动
const springConfig = {
  type: "spring",
  stiffness: 300,
  damping: 30
};

// 多元素 stagger 动效
const staggerChildren = {
  delayChildren: 0.1,
  staggerChildren: 0.05
};

// 尊重用户的减少动效偏好
const shouldAnimate = !window.matchMedia('(prefers-reduced-motion: reduce)').matches;
完整动效模式库请阅读
references/animation-patterns.md

Color: Beyond the Rainbow

色彩:不止于彩虹

Semantic Color Systems

语义化色彩系统

typescript
// Qualitative (categorical data)
const categorical = [
  "#d97706", "#7c3aed", "#059669", "#dc2626", "#2563eb"
];

// Sequential (ordered data, low to high)
const sequential = [
  "#fef3c7", "#fcd34d", "#f59e0b", "#d97706", "#92400e"
];

// Diverging (data with meaningful center)
const diverging = [
  "#dc2626", "#f87171", "#fef2f2", "#c7d2fe", "#6366f1"
];
typescript
// 定性色(分类数据)
const categorical = [
  "#d97706", "#7c3aed", "#059669", "#dc2626", "#2563eb"
];

// 顺序色(有序数据,从低到高)
const sequential = [
  "#fef3c7", "#fcd34d", "#f59e0b", "#d97706", "#92400e"
];

// 发散色(有意义中心值的数据)
const diverging = [
  "#dc2626", "#f87171", "#fef2f2", "#c7d2fe", "#6366f1"
];

Accessibility Requirements

无障碍要求

  • Contrast ratio ≥4.5:1 for text on backgrounds
  • Don't rely on color alone - Use shapes, patterns, labels
  • Colorblind-safe palettes - Test with simulators
  • Consider dark mode - Colors must work in both themes
  • 文本与背景对比度≥4.5:1
  • 不单独依赖色彩 - 使用形状、图案、标签辅助
  • 色盲友好调色板 - 使用模拟器测试
  • 考虑深色模式 - 色彩需在两种主题下都适用

Testing Data Visualizations

测试数据可视化

Visual Regression Testing

视觉回归测试

bash
undefined
bash
undefined

Percy - Automated visual testing

Percy - 自动化视觉测试

npx percy snapshot ./storybook-static
npx percy snapshot ./storybook-static

Chromatic - For Storybook

Chromatic - 用于Storybook

npx chromatic --project-token=<token>
undefined
npx chromatic --project-token=<token>
undefined

Data Accuracy Testing

数据准确性测试

typescript
// Verify rendered elements match data
test('bar chart renders correct number of bars', () => {
  const data = [{ x: 'A', y: 10 }, { x: 'B', y: 20 }];
  render(<BarChart data={data} />);

  const bars = screen.getAllByTestId('bar');
  expect(bars).toHaveLength(2);
});

// Verify scale accuracy
test('bar heights proportional to values', () => {
  const data = [{ x: 'A', y: 10 }, { x: 'B', y: 20 }];
  render(<BarChart data={data} />);

  const bars = screen.getAllByTestId('bar');
  const heights = bars.map(b => parseInt(b.style.height));
  expect(heights[1]).toBe(heights[0] * 2); // B is 2x A
});
Read
references/testing-strategies.md
for comprehensive test suites.
typescript
// 验证渲染元素与数据匹配
test('bar chart renders correct number of bars', () => {
  const data = [{ x: 'A', y: 10 }, { x: 'B', y: 20 }];
  render(<BarChart data={data} />);

  const bars = screen.getAllByTestId('bar');
  expect(bars).toHaveLength(2);
});

// 验证比例尺准确性
test('bar heights proportional to values', () => {
  const data = [{ x: 'A', y: 10 }, { x: 'B', y: 20 }];
  render(<BarChart data={data} />);

  const bars = screen.getAllByTestId('bar');
  const heights = bars.map(b => parseInt(b.style.height));
  expect(heights[1]).toBe(heights[0] * 2); // B是A的2倍
});
全面测试套件请阅读
references/testing-strategies.md

Responsive Design Patterns

响应式设计模式

Mobile-First Approach

移动端优先方法

typescript
// Desktop: Show everything
// Tablet: Simplify axes, reduce labels
// Mobile: Minimal chart, key insights only

const ChartResponsive = ({ data }: Props) => {
  const isMobile = useMediaQuery('(max-width: 640px)');

  return (
    <ResponsiveContainer width="100%" height={isMobile ? 200 : 400}>
      <LineChart data={data}>
        {!isMobile && <CartesianGrid strokeDasharray="3 3" />}
        <XAxis
          dataKey="date"
          tick={isMobile ? { fontSize: 10 } : undefined}
          interval={isMobile ? 'preserveStartEnd' : 'auto'}
        />
        <YAxis tick={isMobile ? false : undefined} />
        <Tooltip />
        <Line type="monotone" dataKey="value" stroke="#d97706" />
      </LineChart>
    </ResponsiveContainer>
  );
};
typescript
// 桌面端:展示全部内容
// 平板端:简化坐标轴、减少标签
// 移动端:极简图表,仅保留核心洞察

const ChartResponsive = ({ data }: Props) => {
  const isMobile = useMediaQuery('(max-width: 640px)');

  return (
    <ResponsiveContainer width="100%" height={isMobile ? 200 : 400}>
      <LineChart data={data}>
        {!isMobile && <CartesianGrid strokeDasharray="3 3" />}
        <XAxis
          dataKey="date"
          tick={isMobile ? { fontSize: 10 } : undefined}
          interval={isMobile ? 'preserveStartEnd' : 'auto'}
        />
        <YAxis tick={isMobile ? false : undefined} />
        <Tooltip />
        <Line type="monotone" dataKey="value" stroke="#d97706" />
      </LineChart>
    </ResponsiveContainer>
  );
};

Touch-Friendly Interactions

触控友好交互

  • Minimum touch target: 44×44px - Tooltips, buttons, interactive elements
  • Swipe gestures - Navigate time series, change views
  • Pinch-to-zoom - For dense charts (use carefully)
  • Long-press context menus - Advanced actions
  • 最小触控目标:44×44px - 提示框、按钮、交互元素
  • 滑动手势 - 导航时间序列、切换视图
  • 捏合缩放 - 用于密集图表(谨慎使用)
  • 长按上下文菜单 - 高级操作

Data Storytelling

数据叙事

Every visualization tells a story. Follow the narrative arc:
  1. Hook - What's the surprising insight?
  2. Context - Why should we care?
  3. Evidence - Show the data clearly
  4. Conclusion - What should we do?
每个可视化都在讲述一个故事。遵循叙事弧线:
  1. 钩子 - 什么是令人惊讶的洞察?
  2. 背景 - 我们为什么要关心?
  3. 证据 - 清晰展示数据
  4. 结论 - 我们应该做什么?

Narrative Techniques

叙事技巧

  • Scrollytelling - Charts animate as user scrolls
  • Progressive disclosure - Start simple, reveal complexity
  • Annotations - Point out the insight, don't make users hunt
  • Comparison - Show before/after, us vs. them, expected vs. actual
Read
references/data-storytelling.md
for narrative frameworks.
  • 滚动叙事 - 用户滚动时图表动画展示
  • 渐进式披露 - 从简单开始,逐步揭示复杂性
  • 注释 - 指出洞察,不要让用户自己寻找
  • 对比 - 展示前后对比、我们与他人对比、预期与实际对比
叙事框架请阅读
references/data-storytelling.md

Common Anti-Patterns

常见反模式

❌ The "Rainbow Vomit" Pie Chart

❌ “彩虹呕吐”饼图

Problem: 12 colors, tiny slices, legend on the side Solution: Max 5 categories, direct labels, consider bar chart instead
问题: 12种颜色、微小切片、侧边图例 解决方案: 最多5个分类,直接标注,考虑改用柱状图

❌ The "Misleading Axis" Bar Chart

❌ “误导性坐标轴”柱状图

Problem: Y-axis doesn't start at zero, exaggerates differences Solution: Always start at zero for bar charts (lines can vary)
问题: Y轴不从0开始,夸大差异 解决方案: 柱状图Y轴始终从0开始(折线图可灵活调整)

❌ The "Dual-Axis Confusion" Line Chart

❌ “双轴混淆”折线图

Problem: Two Y-axes with different scales mislead viewers Solution: Use separate charts or normalize to same scale
问题: 两个Y轴比例尺不同,误导观众 解决方案: 使用单独图表或归一化到相同比例尺

❌ The "3D Perspective" Lie

❌ “3D透视”谎言

Problem: 3D effects distort data perception Solution: Stick to 2D, use color/size for third dimension
问题: 3D效果扭曲数据感知 解决方案: 坚持使用2D,用颜色/尺寸表示第三维度

❌ The "Spinner of Death" Loading State

❌ “死亡加载圈”加载状态

Problem: Empty screen with spinner for 2+ seconds Solution: Skeleton loading that shows chart structure immediately
Read
references/antipatterns.md
for exhaustive catalog.
问题: 空白屏幕加加载圈超过2秒 解决方案: 使用骨架屏立即展示图表结构
完整反模式目录请阅读
references/antipatterns.md

Implementation Workflow

实施工作流

1. Explore Your Data

1. 探索你的数据

bash
undefined
bash
undefined

Use Observable Plot for rapid iteration

使用Observable Plot进行快速迭代

npm install @observablehq/plot
npm install @observablehq/plot

Create throwaway prototypes, iterate fast

创建一次性原型,快速迭代

When you find the right chart, implement in production library

找到合适的图表后,用生产库实现

undefined
undefined

2. Build Production Component

2. 构建生产环境组件

typescript
// Use Recharts for standard charts
// Use Nivo for beautiful, themeable charts
// Use Visx/D3 for custom visualizations

// Always wrap in error boundaries
// Always show skeleton loading state
// Always handle empty/loading/error states
typescript
// 标准图表使用Recharts
// 美观、可定制主题的图表使用Nivo
// 自定义可视化使用Visx/D3

// 始终包裹在错误边界中
// 始终显示骨架屏加载状态
// 始终处理空/加载/错误状态

3. Test Thoroughly

3. 全面测试

bash
undefined
bash
undefined

Visual regression testing

视觉回归测试

npx percy snapshot
npx percy snapshot

Component testing

组件测试

npm test -- --coverage
npm test -- --coverage

Accessibility testing

无障碍测试

npx axe-core src/components/charts
undefined
npx axe-core src/components/charts
undefined

4. Document & Deploy

4. 文档与部署

typescript
// Storybook for component playground
// Props documentation with TypeScript
// Usage examples for each chart type
typescript
// 使用Storybook作为组件演示平台
// 用TypeScript编写Props文档
// 为每种图表类型提供使用示例

AI-Enhanced Visualizations

AI增强可视化

When to Use Claude/Haiku

何时使用Claude/Haiku

  • Dynamic annotations - Generate insights from data
  • Color palette suggestions - AI-powered color harmony
  • Chart type recommendations - "What's the best way to show this?"
  • Accessibility descriptions - Auto-generate alt text
  • 动态注释 - 从数据生成洞察
  • 色彩调色板建议 - AI驱动的色彩和谐
  • 图表类型推荐 - “展示这些数据的最佳方式是什么?”
  • 无障碍描述 - 自动生成替代文本

Example: AI Annotation

示例:AI注释

typescript
const generateInsight = async (data: DataPoint[]) => {
  const response = await fetch('/api/claude', {
    method: 'POST',
    body: JSON.stringify({
      model: 'claude-haiku',
      prompt: `Analyze this data and provide ONE key insight (max 15 words): ${JSON.stringify(data)}`
    })
  });

  return response.text(); // "Sales peaked in Q3, driven by mobile conversions"
};
typescript
const generateInsight = async (data: DataPoint[]) => {
  const response = await fetch('/api/claude', {
    method: 'POST',
    body: JSON.stringify({
      model: 'claude-haiku',
      prompt: `分析这些数据并提供一个核心洞察(最多15字):${JSON.stringify(data)}`
    })
  });

  return response.text(); // "销售额在第三季度达到峰值,由移动端转化驱动"
};

Inspiration Galleries

灵感画廊

Performance Optimization

性能优化

Bundle Size Management

包大小管理

typescript
// ❌ DON'T import entire library
import { LineChart } from 'recharts';

// ✅ DO tree-shake where possible
import LineChart from 'recharts/lib/chart/LineChart';

// Use dynamic imports for heavy charts
const HeavyChart = dynamic(() => import('./HeavyChart'), {
  loading: () => <ChartSkeleton />,
  ssr: false // Disable SSR for client-only charts
});
typescript
// ❌ 不要导入整个库
import { LineChart } from 'recharts';

// ✅ 尽可能使用树摇
import LineChart from 'recharts/lib/chart/LineChart';

// 对重型图表使用动态导入
const HeavyChart = dynamic(() => import('./HeavyChart'), {
  loading: () => <ChartSkeleton />,
  ssr: false // 对仅客户端图表禁用SSR
});

Canvas vs SVG

Canvas vs SVG

  • SVG - Better for < 1000 data points, accessibility, crisp at any scale
  • Canvas - Better for > 1000 data points, animations, performance
  • WebGL - Best for > 10,000 data points, 3D, gaming-level performance
  • SVG - 适合<1000个数据点、无障碍、任意缩放都清晰
  • Canvas - 适合>1000个数据点、动画、性能优先
  • WebGL - 最适合>10000个数据点、3D、游戏级性能

Virtualization

虚拟化

For large datasets, render only visible portion:
typescript
// Use react-window or react-virtualized for long lists
// Aggregate/sample data for chart display
// Store full dataset separately for export
对于大型数据集,仅渲染可见部分:
typescript
// 使用react-window或react-virtualized处理长列表
// 聚合/采样数据用于图表展示
// 单独存储完整数据集用于导出

Accessibility Standards (WCAG AA)

无障碍标准(WCAG AA)

Requirements

要求

  • Keyboard navigation - All interactive elements accessible via Tab
  • Screen reader support - Provide data tables as alternative
  • Focus indicators - Visible focus states for interactive elements
  • Color contrast - ≥4.5:1 for small text, ≥3:1 for large text
  • Reduced motion - Respect
    prefers-reduced-motion: reduce
  • 键盘导航 - 所有交互元素可通过Tab访问
  • 屏幕阅读器支持 - 提供数据表格作为替代方案
  • 焦点指示器 - 交互元素有可见的焦点状态
  • 色彩对比度 - 小文本≥4.5:1,大文本≥3:1
  • 减少动效 - 尊重
    prefers-reduced-motion: reduce
    设置

Implementation

实现示例

typescript
<figure role="img" aria-labelledby="chart-title chart-desc">
  <h2 id="chart-title">Sales Over Time</h2>
  <p id="chart-desc">
    Line chart showing sales increased 45% from Q1 to Q4,
    peaking in November at $2.3M.
  </p>

  <LineChart data={data} />

  {/* Provide data table alternative */}
  <details>
    <summary>View data table</summary>
    <table>...</table>
  </details>
</figure>
typescript
<figure role="img" aria-labelledby="chart-title chart-desc">
  <h2 id="chart-title">销售额随时间变化</h2>
  <p id="chart-desc">
    折线图显示销售额从第一季度到第四季度增长了45%    11月达到峰值230万美元。
  </p>

  <LineChart data={data} />

  {/* 提供数据表格替代方案 */}
  <details>
    <summary>查看数据表格</summary>
    <table>...</table>
  </details>
</figure>

Reference Materials

参考资料

This skill includes comprehensive reference documentation:
  • references/tufte-principles.md
    - Edward Tufte's data visualization principles with examples
  • references/library-comparison.md
    - Deep dive on Observable Plot, Recharts, Nivo, Visx, D3
  • references/testing-strategies.md
    - Visual regression, component testing, accessibility testing
  • references/animation-patterns.md
    - Motion design patterns for charts
  • references/data-storytelling.md
    - Narrative techniques and scrollytelling patterns
  • references/antipatterns.md
    - Common mistakes and how to avoid them
  • references/nyt-workflow.md
    - New York Times graphics team best practices
本技能包含全面的参考文档:
  • references/tufte-principles.md
    - Edward Tufte的数据可视化原则及示例
  • references/library-comparison.md
    - Observable Plot、Recharts、Nivo、Visx、D3的深入对比
  • references/testing-strategies.md
    - 视觉回归、组件测试、无障碍测试
  • references/animation-patterns.md
    - 图表动效设计模式
  • references/data-storytelling.md
    - 叙事技巧和滚动叙事模式
  • references/antipatterns.md
    - 常见错误及避免方法
  • references/nyt-workflow.md
    - 《纽约时报》图形团队最佳实践

Utility Scripts

实用脚本

  • scripts/data-transform.ts
    - Common data transformations (rollup, pivot, normalize)
  • scripts/chart-test-helpers.ts
    - Testing utilities for verifying chart accuracy
  • scripts/color-palette-generator.ts
    - Generate accessible color palettes
  • scripts/performance-benchmark.ts
    - Benchmark chart rendering performance
  • scripts/data-transform.ts
    - 常见数据转换(汇总、透视、归一化)
  • scripts/chart-test-helpers.ts
    - 验证图表准确性的测试工具
  • scripts/color-palette-generator.ts
    - 生成无障碍调色板
  • scripts/performance-benchmark.ts
    - 基准测试图表渲染性能

Quick Start: Building Your First Chart

快速开始:构建你的第一个图表

typescript
// 1. Install dependencies
// npm install recharts framer-motion

// 2. Create a simple line chart
import { LineChart, Line, XAxis, YAxis, Tooltip, ResponsiveContainer } from 'recharts';
import { motion } from 'framer-motion';

const data = [
  { month: 'Jan', value: 400 },
  { month: 'Feb', value: 300 },
  { month: 'Mar', value: 600 },
];

export const SalesChart = () => (
  <motion.div
    initial={{ opacity: 0, y: 20 }}
    animate={{ opacity: 1, y: 0 }}
    transition={{ duration: 0.5 }}
  >
    <ResponsiveContainer width="100%" height={300}>
      <LineChart data={data}>
        <XAxis dataKey="month" />
        <YAxis />
        <Tooltip />
        <Line
          type="monotone"
          dataKey="value"
          stroke="#d97706"
          strokeWidth={2}
          dot={{ fill: '#d97706', r: 4 }}
        />
      </LineChart>
    </ResponsiveContainer>
  </motion.div>
);

// 3. Test it
// 4. Ship it with confidence

Remember: The best visualization is the one that makes the insight obvious. When in doubt, simplify. When confused, prototype 10 options. When shipping, test ruthlessly.
This skill guides: Chart selection | Library integration | Testing strategies | Animation patterns | Accessibility compliance | Performance optimization
typescript
// 1. 安装依赖
// npm install recharts framer-motion

// 2. 创建简单折线图
import { LineChart, Line, XAxis, YAxis, Tooltip, ResponsiveContainer } from 'recharts';
import { motion } from 'framer-motion';

const data = [
  { month: 'Jan', value: 400 },
  { month: 'Feb', value: 300 },
  { month: 'Mar', value: 600 },
];

export const SalesChart = () => (
  <motion.div
    initial={{ opacity: 0, y: 20 }}
    animate={{ opacity: 1, y: 0 }}
    transition={{ duration: 0.5 }}
  >
    <ResponsiveContainer width="100%" height={300}>
      <LineChart data={data}>
        <XAxis dataKey="month" />
        <YAxis />
        <Tooltip />
        <Line
          type="monotone"
          dataKey="value"
          stroke="#d97706"
          strokeWidth={2}
          dot={{ fill: '#d97706', r: 4 }}
        />
      </LineChart>
    </ResponsiveContainer>
  </motion.div>
);

// 3. 测试
// 4. 自信地上线

记住: 最好的可视化是能让洞察显而易见的可视化。有疑问时,简化内容。困惑时,制作10个原型。上线时,严格测试。
本技能涵盖:图表选择 | 库集成 | 测试策略 | 动画模式 | 无障碍合规 | 性能优化