Visx logo

Visx

一套由 Airbnb 开源的低层级 React 可视化原语组件库,将 D3 的数学计算能力与 React 的声明式渲染相结合,让开发者像搭积木一样构建高度定制化的数据可视化图表。

可视化图表ReactAirbnb

Visx 是 Airbnb 开源的 React 可视化原语组件库,将 D3 的数学计算能力封装为符合 React 心智模型的组件,不预设图表类型,让开发者按需选取、自由拼装高度定制化的数据可视化,v4.0.0 已支持 React 19。

Visx — Airbnb 出品可视化组件集合

一套由 Airbnb 开源的低层级 React 可视化原语组件库,将 D3 的数学计算能力与 React 的声明式渲染相结合,让开发者像搭积木一样构建高度定制化的数据可视化图表。

技术简介说明

Visx(读作 "vis-x",全称 visualization components)是 Airbnb 工程团队开发并开源的一组 React 可视化组件集合。它的核心理念并非提供一个"开箱即用"的图表库,而是将可视化拆解为可组合的低层级原语(primitives)——如坐标轴、形状、比例尺、工具提示、网格等——让开发者按需选取、自由拼装,构建出完全自定义的数据可视化作品。

在项目哲学上,Visx 刻意保持"无主见"(unopinionated)。它不预设图表类型、不强制布局方式、不捆绑动画库,而是将 D3 强大的数学与计算能力(比例尺、路径生成、曲线插值、形状计算等)封装成符合 React 心智模型的组件,由开发者掌控最终的渲染输出。这种设计使得 Visx 在灵活性、包体积控制方面表现卓越,但也意味着开发者需要承担更多的组装工作。

Visx 诞生于 Airbnb 内部的数据可视化需求,前身为 vx 项目,后更名为 visx 并发布了 30 多个独立 npm 包。截至 2026 年 6 月,最新版本 v4.0.0 带来了 React 19 支持和 D3 依赖升级,解决了社区对维护节奏的担忧。它在 Airbnb 内部及全球开源社区中被广泛使用,是 React 生态中最灵活的可视化构建工具之一。

基本信息

  • 官网https://visx.airbnb.tech/
  • GitHubhttps://github.com/airbnb/visx
  • License:MIT
  • 最新版本:v4.0.0(2026-06-11)
  • GitHub Stars:约 20.9k
  • 主要维护者/公司:Airbnb 工程团队(Chris Williams 为核心贡献者)
  • 包管理器:pnpm monorepo
  • 语言:TypeScript(98.2%)
  • NPM 周下载量:约 500k+(所有包合计)

快速上手

安装

Visx 采用模块化设计,你可以选择安装全部包或按需安装单个包。

方式一:安装全部包(适合快速体验)

# npm
npm install @visx/visx
 
# yarn
yarn add @visx/visx
 
# pnpm
pnpm add @visx/visx

方式二:按需安装(推荐生产环境)

# 常用组合示例
pnpm add @visx/shape @visx/scale @visx/axis @visx/group @visx/responsive @visx/tooltip @visx/grid
 
# 按需求逐步添加
pnpm add @visx/glyph      # 数据点标记
pnpm add @visx/brush       # 范围选择
pnpm add @visx/annotation  # 图表标注
pnpm add @visx/curve       # 曲线插值

基础配置

Visx 需要 React 18 或 React 19 作为 peer dependency:

{
  "peerDependencies": {
    "react": "^18.0.0 || ^19.0.0"
  }
}

无需特殊的构建配置,兼容所有标准 React 项目(Create React App、Next.js、Vite 等)。如需 TypeScript 支持,Visx 自带类型声明。

最小示例

一个基本的柱状图示例:

import React from 'react';
import { Bar } from '@visx/shape';
import { Group } from '@visx/group';
import { scaleBand, scaleLinear } from '@visx/scale';
import { letterFrequency } from '@visx/mock-data';
 
// 数据
const data = letterFrequency.slice(0, 10);
 
// 尺寸
const width = 500;
const height = 300;
const margin = { top: 20, right: 20, bottom: 40, left: 40 };
 
// 比例尺
const xScale = scaleBand<string>({
  range: [0, width - margin.left - margin.right],
  domain: data.map((d) => d.letter),
  padding: 0.2,
});
 
const yScale = scaleLinear<number>({
  range: [height - margin.top - margin.bottom, 0],
  domain: [0, Math.max(...data.map((d) => d.frequency))],
});
 
// 颜色
const color = '#612efb';
 
function BarChart() {
  const innerWidth = width - margin.left - margin.right;
  const innerHeight = height - margin.top - margin.bottom;
 
  return (
    <svg width={width} height={height}>
      <Group top={margin.top} left={margin.left}>
        {data.map((d) => {
          const barWidth = xScale.bandwidth();
          const barHeight = innerHeight - (yScale(d.frequency) ?? 0);
          const x = xScale(d.letter) ?? 0;
          const y = yScale(d.frequency) ?? 0;
          return (
            <Group key={`bar-${d.letter}`}>
              <Bar
                x={x}
                y={y}
                width={barWidth}
                height={barHeight}
                fill={color}
              />
            </Group>
          );
        })}
      </Group>
    </svg>
  );
}
 
export default BarChart;

核心概念与架构

设计哲学

Visx 的架构遵循三个核心原则:

  1. D3 计算 + React 渲染:D3 负责数学运算(比例尺、路径生成、曲线插值等),React 负责 DOM 渲染和状态管理。Visx 不使用 D3 的 DOM 操作(selections),避免了两种 DOM 心智模型的冲突。

  2. 可组合原语:每个包对应一个可视化概念(轴、形状、网格、标注等),它们是可以自由组合的"乐高积木",而非预制的完整图表。

  3. 按需引入:30+ 独立包的设计允许开发者只引入真正需要的功能,将 bundle size 控制在最小范围内。

包架构

Visx 采用 pnpm monorepo 架构,包含以下核心包层级:

底层工具层
├── @visx/scale        # D3 比例尺封装(linear、band、ordinal、time 等)
├── @visx/curve        # D3 曲线插值封装
├── @visx/point        # 二维点工具类
├── @visx/bounds       # 边界计算工具
│
渲染原语层
├── @visx/shape        # 基础形状(Bar、Line、Area、Pie、Arc 等)
├── @visx/glyph        # 数据点标记(Circle、Cross、Dot、Star 等)
├── @visx/text         # 文本渲染组件(支持自动换行)
├── @visx/group        # SVG <g> 分组组件
│
图表组件层
├── @visx/axis         # 坐标轴组件(可配置方向、刻度、标签)
├── @visx/grid         # 网格线组件
├── @visx/annotation   # 图表标注(标签、连线、区域高亮)
│
交互层
├── @visx/tooltip      # 工具提示(hooks、HOC、Tooltip 组件)
├── @visx/brush        # 范围选择/缩放组件
│
高级层
├── @visx/xychart      # 高级图表组件(内置动画轴、网格、提示等)
├── @visx/responsive   # 响应式图表容器
│
辅助层
├── @visx/mock-data    # 测试用模拟数据
├── @visx/visx         # 全量元包(re-export 所有子包)

数据流

原始数据 → scale(比例尺映射) → shape/glyph(形状计算) → React 组件渲染 → SVG DOM
                     ↑                      ↑
              D3 数学计算             D3 路径生成

Visx 不管理数据状态——数据通过 props 传入,比例尺负责将数据域映射到像素域,形状组件负责将映射结果渲染为 SVG 元素。

核心特性

  • 模块化按需引入:30+ 独立 npm 包,开发者只安装需要的功能,bundle 最小可控制在几 KB
  • D3 数学 + React 渲染:充分利用 D3 成熟的计算生态,同时保持 React 声明式、组件化、虚拟 DOM 的优势
  • 不捆绑动画:刻意不内置动画系统,允许开发者自由选择 framer-motion、react-spring、GSAP 等任意动画方案
  • TypeScript 优先:100% TypeScript 编写,类型安全、完善的类型推断
  • 高度可定制:每个组件都暴露底层 SVG 属性,支持完全自定义样式和行为
  • React 18/19 支持:v4.0.0 起支持 React 18 和 React 19,兼容 Concurrent Features
  • 无主见设计:不预设图表类型、不强制布局方式,开发者完全掌控最终输出
  • 丰富的 Gallery:官方提供大量可交互示例,可直接查看源码和复制使用
  • @visx/xychart 高级抽象:在需要快速构建标准图表时,提供更高层级的封装(内置动画、主题、响应式)
  • Server-Side Rendering 兼容:SVG 渲染天然支持 SSR,适用于 Next.js 等框架

生态图

关键依赖

依赖用途
d3-scale比例尺计算
d3-shape (v3)路径/形状生成
d3-path (v3)SVG 路径命令
d3-array数组工具函数
d3-interpolate值插值
d3-color颜色处理
@react-spring/webxychart 动画依赖(可选)
react (18/19)核心渲染引擎

框架集成

Visx 是纯 React 组件库,与以下框架/工具天然兼容:

  • Next.js:支持 SSR / SSG,SVG 在服务端和客户端均可渲染
  • Vite:零配置开箱使用
  • Create React App:完全兼容
  • Remix:支持服务端渲染
  • Storybook:适合组件开发和文档展示

社区生态

  • Visx Galleryvisx.airbnb.tech):官方示例画廊,涵盖各类图表类型
  • PureScript 绑定:社区维护的 purescript-visx
  • Vue 移植参考:部分社区项目参考 Visx 理念为 Vue 提供类似原语

相关项目

  • @react-spring/web:推荐的动画方案之一
  • framer-motion:另一流行的 React 动画库
  • d3:底层数学计算的核心依赖

适用场景

  • 高度定制化数据可视化:当你需要完全掌控图表的每个像素,标准图表库无法满足设计需求时,Visx 是最佳选择
  • 品牌化图表系统:需要图表与品牌设计系统深度整合,包括自定义形状、动画、交互模式
  • 大规模 Dashboard 应用:企业级应用中需要多种类型的可视化组件,且对 bundle size 有严格要求
  • 数据新闻与叙事可视化:媒体、新闻行业中需要创造独特、富有表现力的数据故事
  • 可复用图表组件库:基于 Visx 原语构建团队内部的图表组件库,统一可视化规范
  • 交互式探索工具:需要 brush 缩放、范围选择、动态标注等复杂交互的可视化
  • 轻量级图表需求:当只需要一两种简单图表类型,不想引入完整图表库的重量级依赖

开发与工程化

开发流程

Visx monorepo 使用以下工具链:

# 克隆仓库
git clone https://github.com/airbnb/visx.git
cd visx
 
# 安装依赖(使用 yarn)
yarn install
 
# 启动 Storybook 开发服务器
yarn dev
 
# 运行测试
yarn test
 
# 构建
yarn build
 
# Lint 检查
yarn lint

在项目中集成 Visx

推荐的工程化实践:

src/
├── components/
│   ├── charts/
│   │   ├── BarChart/
│   │   │   ├── index.tsx          # 图表组件
│   │   │   ├── BarChart.test.tsx  # 测试
│   │   │   └── types.ts           # 类型定义
│   │   ├── LineChart/
│   │   └── PieChart/
│   ├── shared/
│   │   ├── ChartTooltip.tsx       # 共享 tooltip 组件
│   │   ├── ChartAxis.tsx          # 自定义轴组件
│   │   └── ChartTheme.ts          # 主题常量
│   └── hooks/
│       ├── useChartDimensions.ts   # 响应式尺寸 hook
│       └── useChartData.ts         # 数据处理 hook

CI/CD 集成

Visx 与任何标准 React 项目的 CI/CD 流程兼容:

  • 视觉回归测试:推荐使用 Chromatic、Percy 或 Playwright 截图对比
  • TypeScript 检查tsc --noEmit 确保类型安全
  • Bundle 分析:使用 webpack-bundle-analyzersource-map-explorer 监控包体积
  • 自动化测试:Jest + React Testing Library 进行组件单元测试

构建优化

// ❌ 避免:引入全量包
import { Bar, Line, Area } from '@visx/visx';
 
// ✅ 推荐:按需引入
import { Bar } from '@visx/shape';
import { Line } from '@visx/shape';

性能与安全

性能特点

  • 极小 Bundle Size:按需引入时,单个组件仅增加几 KB(gzip 后)。例如 @visx/shapeBar 组件约 1-2 KB
  • 无运行时开销:Visx 组件最终渲染为标准 SVG 元素,没有额外的运行时抽象层
  • React 虚拟 DOM 友好:SVG 元素通过 React 的 diff 算法高效更新
  • 大数据集注意事项:渲染上万个 SVG 元素时可能遇到性能瓶颈,此时应考虑 Canvas 渲染或数据降采样

优化建议

  1. 使用 React.memo 包裹图表组件:避免父组件重渲染导致的不必要图表重绘
  2. 合理选择比例尺类型scaleBand 用于分类数据,scaleLinear 用于连续数据
  3. 利用 @visx/responsive:通过 withParentSizeuseParentSize 实现自适应,避免硬编码尺寸
  4. 大数据集用 Canvas:当数据点超过数千个时,考虑结合 @visx/glyph 的 Canvas 渲染模式
  5. 避免在 render 中创建比例尺:使用 useMemo 缓存比例尺实例
// ✅ 推荐:缓存比例尺
const xScale = useMemo(
  () => scaleBand({ range: [0, width], domain: data.map(d => d.key), padding: 0.1 }),
  [width, data]
);
 
// ❌ 避免:每次 render 都重新创建
const xScale = scaleBand({ range: [0, width], domain: data.map(d => d.key), padding: 0.1 });

安全注意事项

  • Visx 渲染标准 SVG,不涉及 dangerouslySetInnerHTML,XSS 风险极低
  • 确保传入的数据不包含恶意脚本(SVG &lt;text&gt; 元素只渲染纯文本)
  • 如果 Tooltip 内容来自用户输入,需进行 HTML 转义处理

已知性能瓶颈

  • 大量 SVG 元素:SVG 元素超过 5000-10000 个时,浏览器渲染和交互可能出现卡顿
  • 复杂路径计算:D3 路径生成在大数据集上可能消耗较多 CPU 时间
  • 频繁重渲染:未优化的 props 变化(如每次 render 生成新数组引用)会导致不必要的 diff

技术对比

与同类 React 图表库对比

特性VisxRechartsNivoVictoryD3.js
定位低层级原语声明式图表库声明式+丰富配置声明式图表库底层可视化库
抽象层级极低(积木式)中等中等中等极低
学习曲线较陡峭平缓中等中等极陡峭
Bundle Size极小(按需引入)中等(~160KB)较大(~186KB)中等中等(~90KB)
灵活性极高中等中等中等极高
预置图表无(需自己组装)丰富丰富丰富
动画支持自选内置内置内置自选
TypeScript原生良好良好一般社区类型
React 19 支持✅ v4.0.0⚠️ 部分N/A
SSR 支持⚠️ 有限
维护方Airbnb社区ploucFormidableD3 社区
GitHub Stars~20.9k~24k~13k~10.6k~110k
LicenseMITMITMITMITISC

选型建议

  • 选 Visx:需要完全定制图表外观和行为、对 bundle size 敏感、有能力投入开发时间组装组件
  • 选 Recharts:快速搭建标准图表、团队偏好简单的声明式 API、不需要深度定制
  • 选 Nivo:需要丰富的预置图表类型、好看的默认样式、服务端渲染支持
  • 选 Victory:需要跨平台(React Native)、团队偏好声明式 API
  • 选 D3.js:需要极致的灵活性、不依赖 React、需要创建前所未有的可视化形式

最佳实践

生产环境建议

  1. 按需引入包:永远不要在生产环境使用 @visx/visx 全量包,只安装需要的子包
// ❌ 生产环境不推荐
import { Bar, Line, Axis } from '@visx/visx';
 
// ✅ 生产环境推荐
import { Bar, Line } from '@visx/shape';
import { Axis } from '@visx/axis';
  1. 统一主题管理:将颜色、字体、间距等抽取为主题常量
// chartTheme.ts
export const CHART_COLORS = {
  primary: '#612efb',
  secondary: '#ff6b6b',
  grid: '#e0e0e0',
  text: '#333333',
  background: '#ffffff',
};
 
export const CHART_MARGIN = { top: 20, right: 20, bottom: 40, left: 50 };
  1. 响应式设计:使用 @visx/responsiveuseParentSize hook
import { useParentSize } from '@visx/responsive';
 
function ResponsiveChart({ data }) {
  const { parentRef, width } = useParentSize();
 
  return (
    <div ref={parentRef}>
      {width > 0 && <MyChart width={width} height={width * 0.6} data={data} />}
    </div>
  );
}
  1. 性能优化:使用 React.memouseMemo 避免不必要的重渲染

  2. 可访问性:添加 aria-labelrole="img" 等属性提升可访问性

<svg role="img" aria-label="2024年季度收入柱状图">
  {/* 图表内容 */}
</svg>

常见陷阱

  • 忘记 margin:SVG 的坐标从左上角开始,轴标签可能被裁切,需要预留 margin
  • 比例尺域错误:确保 domain 覆盖数据的完整范围,避免数据点超出可视区域
  • 忽略响应式:硬编码的固定宽高在不同屏幕尺寸下体验差
  • 动画与性能:在大数据集上使用复杂动画会导致卡顿
  • SSR hydration 不匹配:使用 useParentSize 时,服务端无法获取容器尺寸,需要设置合理的初始值

推荐模式

  • 组合模式:将 Visx 原语封装为团队内部的高级图表组件
  • Hook 模式:将数据处理、尺寸计算、交互逻辑抽取为自定义 hooks
  • 配置模式:通过配置对象统一管理图表的视觉风格

技术局限与边界

已知限制

  1. 不是完整图表库:Visx 不提供开箱即用的图表,所有图表都需要开发者自行组装
  2. 仅支持 React:没有 Vue、Angular 或原生 JS 版本,不可用于非 React 项目
  3. SVG 渲染为主:虽然支持 Canvas,但核心以 SVG 为主,不适合超大规模数据渲染(10 万+数据点)
  4. 维护节奏不稳定:社区曾讨论过维护频率下降的问题(#1908),v4.0.0 发布后有所改善
  5. 文档有限:官方文档相对简洁,部分包缺少详细的 API 文档,需要参考示例和源码
  6. 无内置交互:zoom、pan、lasso 等交互需要自行实现或借助其他库

不适用场景

  • 快速原型:需要在几分钟内出图表时,Recharts 或 Chart.js 更高效
  • 非 React 项目:Vue、Angular、Svelte 项目应选择对应生态的图表库
  • 超大数据可视化:10 万+数据点的实时渲染应选择 Deck.gl、LightningChart 等专业方案
  • 标准商业报表:需要标准 Excel 风格图表时,Highcharts 或 ECharts 更合适
  • 3D 可视化:Visx 完全不支持 3D,需要 Three.js 或 react-three-fiber

权衡取舍

选择 Visx 你得到选择 Visx 你放弃
极致的定制化能力开箱即用的便利性
最小的 bundle size快速出图的开发效率
灵活的技术选型内置动画和交互
组件化组合模式统一的图表 API

迁移注意事项

  • 从 Recharts 迁移到 Visx:需要重新实现所有图表的组装逻辑,工作量大
  • 从 D3 迁移到 Visx:可以复用大部分 D3 计算逻辑,主要改动是 DOM 操作替换为 React 组件
  • 从 Visx v3 升级到 v4:需要升级 React 到 18+,检查 d3-shape/d3-path v3 的 breaking changes

学习资源

官方资源

教程

社区资源

视频资源

2026 年现状

最新版本

  • v4.0.0(2026-06-11)是最新的重大版本更新,主要变更:
    • 所有包添加 React 19 到 peer dependencies
    • 升级 d3-shaped3-path 到 v3
    • 要求 React 18 或 19
    • 包含 v4 迁移指南

发展趋势

  • 维护回暖:在经历了一段时间的低活跃度后(社区 #1908 讨论),v4.0.0 的发布表明项目重新获得了维护动力
  • React 生态同步:及时支持 React 19 是重要信号,说明团队在跟进 React 生态演进
  • 稳定期:Visx 的核心 API 已经相当稳定,breaking changes 较少

社区活跃度

  • GitHub Stars:约 20.9k,在 React 可视化库中排名前列
  • Issue & PR:社区保持一定的活跃度,但核心贡献者相对集中
  • NPM 下载量:保持稳定增长,说明实际使用量持续扩大

未来展望

  • Visx 作为 Airbnb 的开源项目,其维护节奏与公司内部需求密切相关
  • 社区期待更多高级组件(如 @visx/xychart 的增强)和更好的文档
  • 随着 React Server Components 的普及,Visx 的 SVG 渲染模式天然适配服务端渲染
  • 潜在方向:WebGL/Canvas 渲染支持增强、更好的大数据集支持

总结:Visx 是 React 生态中灵活性最高的可视化构建工具,适合对图表定制化和 bundle size 有严格要求的团队。它不是"开箱即用"的图表库,而是一套精心设计的可视化原语——选择它意味着选择掌控力,同时也意味着承担更多组装工作。