Victory
基于 D3 的 React 图表库,业界唯一成熟的 Web + React Native 跨平台数据可视化解决方案。
Victory 是唯一同时支持 Web(SVG)和 React Native(Skia GPU)的成熟 React 图表库,Web 端基于 D3 数学计算和 SVG 渲染,Native 端使用 Skia GPU 加速实现 60+ FPS 动画,是跨平台数据可视化的首选方案。
Victory
基于 D3 的 React 图表库,业界唯一成熟的 Web + React Native 跨平台数据可视化解决方案。
技术简介说明
Victory 是由 Formidable Labs 创建、现由 Nearform 维护的 React 图表库。其核心定位是提供一套统一的组件 API 同时支持 Web(SVG 渲染)和 React Native(Skia GPU 渲染),这使得 Victory 在 React 生态中占据了一个独特的生态位——当项目需要同时在 Web 和移动端(iOS/Android)展示一致的图表体验时,Victory 几乎是唯一成熟的开源选择。
Victory 的架构基于 D3.js 做数学计算(scales、domains、path 生成),但不依赖 D3 的 DOM 操作。Web 端使用纯 SVG 渲染,React Native 端(Victory Native XL, v40+)使用 @shopify/react-native-skia 做 GPU 加速渲染,配合 react-native-reanimated 实现独立 JS 线程的 60+ FPS 动画。这种架构让 Victory Native XL 在低端设备上也能达到流畅的图表交互体验。
Victory 项目分为两条产品线:victory(Web 端,当前 v37.x)和 victory-native-xl(React Native 端,当前 v41.x)。Web 端处于稳定维护模式,以 bug 修复和类型改进为主;React Native 端则是当前最活跃的发展方向,基于 Skia 的重写带来了显著的性能提升和全新的功能规划。
基本信息
- 官网:https://commerce.nearform.com/open-source/victory/
- GitHub (Web):https://github.com/FormidableLabs/victory
- GitHub (Native):https://github.com/FormidableLabs/victory-native-xl
- License:MIT
- 最新版本:v37.3.6(Web,2025 年 1 月 14 日)/ v41.26.0(React Native,2026 年 6 月)
- 主要维护者:Nearform(原 Formidable Labs 创建)
- npm 周下载量:~440,000(Web)
- GitHub Stars:~11,200(Web)/ ~3,500(Native XL)
- React 版本要求:>= 16.3.0
快速上手
安装
Web 端
# npm
npm install victory
# yarn
yarn add victory
# pnpm
pnpm add victoryWeb 端为单包安装,所有图表组件包含在
victory包中。
React Native 端
# 安装 Victory Native XL
pnpm add victory-native
# 安装 peer dependencies(必需)
pnpm add @shopify/react-native-skia
pnpm add react-native-reanimated
pnpm add react-native-gesture-handler重要:Victory Native XL (v40+) 需要安装上述三个 peer dependencies,缺一不可。
基础配置
Web 端
Victory Web 端零配置即可使用,无需 Provider 或全局设置。通过 VictoryTheme 设置全局主题:
import { VictoryTheme } from 'victory'
// 使用内置主题
<VictoryChart theme={VictoryTheme.material}>React Native 端
需要在 App 根组件配置 GestureHandlerRootView:
import { GestureHandlerRootView } from 'react-native-gesture-handler'
export default function App() {
return (
<GestureHandlerRootView style={{ flex: 1 }}>
<YourApp />
</GestureHandlerRootView>
)
}最小示例
Web 端
import {
VictoryChart,
VictoryLine,
VictoryBar,
VictoryAxis,
VictoryTooltip,
VictoryVoronoiContainer,
} from 'victory'
const data = [
{ x: 1, y: 2 },
{ x: 2, y: 3 },
{ x: 3, y: 5 },
{ x: 4, y: 4 },
{ x: 5, y: 6 },
]
export default function App() {
return (
<VictoryChart
// 使用 Voronoi 容器实现 hover 交互
containerComponent={
<VictoryVoronoiContainer
voronoiDimension="x"
labels={({ datum }) => `y: ${datum.y}`}
labelComponent={<VictoryTooltip />}
/>
}
>
<VictoryAxis
label="X 轴"
/>
<VictoryAxis
dependentAxis
label="Y 轴"
/>
<VictoryLine
data={data}
style={{
data: { stroke: '#8884d8', strokeWidth: 3 },
}}
/>
</VictoryChart>
)
}React Native 端
import { CartesianChart, Line } from 'victory-native'
import { useSharedValue } from 'react-native-reanimated'
const DATA = (length: number = 10) =>
Array.from({ length }, (_, index) => ({
x: index + 1,
y: Math.random() * 10,
}))
export function MyChart() {
const data = useSharedValue(DATA())
return (
<CartesianChart data={data} xKey="x" yKeys={['y']}>
{({ points }) => (
<Line points={points.y} color="red" />
)}
</CartesianChart>
)
}核心概念与架构
Web 端架构
用户数据输入
↓
D3 Scales 计算 (d3-scale, d3-shape)
↓
React 组件渲染 (VictoryChart → VictoryLine/Bar/Pie...)
↓
SVG 元素输出
↓
React Reconciliation
↓
DOM 更新
Web 端核心组件层次:
VictoryChart (图表容器,管理坐标系)
├── VictoryAxis / VictoryAxis (坐标轴)
├── VictoryLine / VictoryBar / VictoryArea (数据组件)
├── VictoryScatter (散点)
├── VictoryPie (饼图,独立容器)
├── VictoryGroup (组件分组)
├── VictoryStack (堆叠图表)
└── Container Components
├── VictoryZoomContainer (缩放)
├── VictoryVoronoiContainer (Voronoi hover)
├── VictorySelectionContainer (区域选择)
└── VictoryCursorContainer (光标追踪)
React Native 端架构(Victory Native XL)
用户数据输入 (SharedValue)
↓
Skia GPU 渲染 (React Native Skia)
↓
Reanimated 动画 (独立 JS 线程)
↓
Gesture Handler 手势交互
React Native XL 的核心架构变化:
- 渲染层:从 SVG 转向 React Native Skia(GPU 加速)
- 动画层:从内置动画转向 Reanimated(独立 JS 线程,不阻塞 UI)
- 交互层:使用 React Native Gesture Handler(原生手势识别)
数据绑定模型
// Web 端:通过 data prop
<VictoryBar data={[{ x: 'A', y: 1 }, { x: 'B', y: 2 }]} />
// React Native XL:通过 xKey/yKeys
<CartesianChart data={data} xKey="x" yKeys={['y']}>
{({ points }) => <Line points={points.y} />}
</CartesianChart>组合模式
Victory 强调组件组合而非配置:
// Web 端组合示例
<VictoryChart>
<VictoryStack>
<VictoryBar data={data1} style={{ data: { fill: 'red' } }} />
<VictoryBar data={data2} style={{ data: { fill: 'blue' } }} />
</VictoryStack>
</VictoryChart>核心特性
- 跨平台统一:唯一成熟的 Web + React Native 统一 API 方案,一套代码在 Web、iOS、Android 上运行
- D3 驱动计算:使用 D3 的 scales、shapes 做数学计算,确保数据映射的准确性
- GPU 加速渲染(React Native):Victory Native XL 使用 Skia 实现 GPU 加速,低端设备可达 100+ FPS
- 组合式 API:通过组件组合(
VictoryStack、VictoryGroup、createContainer)而非复杂配置构建图表 - 容器交互系统:
createContainer支持组合多种交互行为(zoom + tooltip + selection) - 主题系统:内置多套主题(
material、grayscale、clean),支持完全自定义 - 动画支持:Web 端内置动画;Native 端使用 Reanimated 实现流畅过渡
- TypeScript 支持:完整的 TypeScript 类型定义,v37.3.3+ 升级至 TypeScript 5.7.2
- 事件系统:丰富的
eventsprop 支持点击、hover、拖拽等交互 - 可组合图表:轻松实现堆叠图、分组图、多 Y 轴等复杂图表组合
- Clean Theme:v37.3.0+ 引入的 Clean Theme 新主题系统,更现代的默认样式
生态图
关键依赖
Web 端
| 依赖 | 用途 |
|---|---|
d3-scale | 比例尺计算 |
d3-shape | 图形路径生成 |
d3-interpolate | 值插值 |
d3-voronoi | Voronoi 图(hover 交互) |
d3-array | 数组工具 |
fast-deep-equal | 深比较(性能优化) |
react-fast-compare | React 优化比较 |
React Native 端(Victory Native XL)
| 依赖 | 用途 |
|---|---|
@shopify/react-native-skia | GPU 加速渲染 |
react-native-reanimated | 动画引擎(独立 JS 线程) |
react-native-gesture-handler | 手势交互 |
d3-scale | 比例尺计算 |
d3-shape | 图形路径生成 |
相关工具
| 工具 | 说明 |
|---|---|
victory-native | React Native 图表组件(v40+ 为 XL 版) |
createContainer | 组合多种交互容器 |
victory-cli | 服务端生成图表图片 |
社区生态
- npm 周下载量:~440K(Web)
- GitHub Stars:~11,200(Web)+ ~3,500(Native XL)
- GitHub Issues:~84 个 open issues(Web)
- Discussions:GitHub Discussions 活跃
- Shopify 工程博客:Shopify 持续发布 Skia/Reanimated 相关技术文章
- Formidable Labs 支持:虽已由 Nearform 维护,Formidable 仍有影响力
适用场景
- Web + React Native 跨平台项目:Victory 最核心的价值——需要同一套图表代码在 Web 和移动端运行
- React Native 移动应用:Victory Native XL 是 React Native 生态中最成熟的图表库
- 高性能移动端图表:Skia GPU 渲染在低端设备上可达 100+ FPS,适合性能敏感的移动应用
- 需要复杂交互的图表:
createContainer组合 zoom、tooltip、selection 等多种交互 - 堆叠/分组图表:
VictoryStack和VictoryGroup组件使复杂组合图表简单易用 - 企业级数据应用:Formidable Labs / Nearform 维护,有商业支持背景
- 实时数据可视化(移动端):Victory Native XL 的 Reanimated 动画和 Streaming Data 规划适合实时数据场景
开发与工程化
开发流程
Web 端
# 克隆仓库
git clone https://github.com/FormidableLabs/victory.git
cd victory
# 安装依赖
pnpm install
# 启动开发环境
pnpm start
# 运行测试
pnpm test
# 类型检查
pnpm typecheck
# 构建
pnpm buildReact Native 端
# 克隆仓库
git clone https://github.com/FormidableLabs/victory-native-xl.git
cd victory-native-xl
# 安装依赖
pnpm install
# 启动示例应用
cd apps/example
pnpm start构建配置
Web 端输出格式:
dist/
├── victory.js # UMD
├── victory.min.js # UMD 压缩
├── victory.es.js # ES Module
├── victory.cjs.js # CommonJS
└── index.d.ts # TypeScript 类型
React Native 端输出为 ES Module,供 Metro bundler 处理。
工程化最佳实践
-
使用
createContainer组合交互const ZoomVoronoi = createContainer('zoom', 'voronoi') <VictoryChart containerComponent={<ZoomVoronoi />} /> -
锁定依赖版本:Victory 的 minor 版本可能引入 breaking changes
-
React Native 端确保 peer deps 版本匹配:Skia 和 Reanimated 的版本需要与 Victory Native XL 兼容
-
Bundle size 分析:Web 端支持 tree-shaking,使用 named imports
-
CI/CD 集成:运行
pnpm test+pnpm typecheck+pnpm build确保质量
性能与安全
性能特点
| 平台 | 数据量 | 帧率 | 备注 |
|---|---|---|---|
| Web (SVG) | < 500 点 | 流畅 | 适合中小数据量 |
| Web (SVG) | 500-2,000 点 | 一般 | 考虑数据降采样 |
| Native (Skia) | < 5,000 点 | 100+ FPS | GPU 加速 |
| Native (Skia) | 5,000-20,000 点 | 60+ FPS | 流畅动画 |
| Native (Skia) | 20,000+ 点 | 30-60 FPS | 仍可接受 |
性能优化建议
-
Web 端大数据量
// 使用 downsample 或限制渲染数据量 const downsampledData = useMemo(() => lttb(rawData, 500), [rawData]) -
React Native 端使用 SharedValue
// 使用 shared value 避免 JS 线程阻塞 const data = useSharedValue(rawData) <CartesianChart data={data} xKey="x" yKeys={['y']}> -
关闭不需要的动画
<VictoryLine animate={false} /> -
使用
eventsprop 替代全局事件// 精确控制事件触发范围,避免不必要的重渲染 events={[{ target: 'data', eventHandlers: { onMouseEnter: () => [{ target: 'data', mutation: ... }] } }]} -
使用
VictoryClipContainer裁剪优化// 避免渲染超出坐标系的元素 <VictoryChart clipContainerComponent={<VictoryClipContainer />} />
安全注意事项
- SVG 渲染不直接执行用户代码,XSS 风险较低
- 自定义
labelComponent时避免使用dangerouslySetInnerHTML - 事件处理器中注意数据验证
已知性能瓶颈
- Web 端 SVG 渲染在超过 2,000 数据点时性能下降明显
createContainer组合多种交互时事件处理开销增加- Web 端缺少 Canvas 渲染选项(与 Chart.js / Nivo Canvas 相比劣势)
- React Native 端 Skia 依赖较大,增加 App 安装包体积
技术对比
| 维度 | Victory | Recharts | Nivo | visx | Chart.js |
|---|---|---|---|---|---|
| GitHub Stars | ~11,200 | ~25,600 | ~14,000 | ~19,000 | ~65,000 |
| 周下载量 | ~440K | ~9M | ~650K | ~3M | ~5M |
| 渲染方式 | SVG (Web) / Skia (Native) | SVG | SVG/Canvas/HTML | SVG | Canvas |
| 跨平台 | ✅ Web + RN | ❌ 仅 Web | ❌ 仅 Web | ❌ 仅 Web | ❌ 仅 Web |
| React Native | ✅ 成熟支持 | ❌ | ❌ | ❌ | ❌ |
| D3 依赖 | 部分(计算) | 部分(计算) | 部分(计算) | 部分(计算) | ❌ 无 |
| 学习曲线 | 中等 | 低 | 中等 | 高 | 低 |
| 自定义能力 | 中高 | 中 | 中高 | 极高 | 中 |
| 动画 | 内置 / Reanimated (Native) | 内置 | react-spring | 需自建 | 内置 |
| TypeScript | ✅ | ✅ | ✅ | ✅ | ✅ (社区) |
| 商业维护 | Nearform | 社区 | 个人 | Airbnb | 社区 |
选型建议
- Web + React Native 统一方案 → Victory(唯一选择)
- 纯 Web 后台图表 → Recharts(社区最大,教程最多)
- 视觉效果优先 → Nivo(动画和图表类型最丰富)
- 极致自定义 → visx(底层原语)
- 非 React 项目 → Chart.js / ECharts
最佳实践
生产环境推荐模式
-
Web 端使用
createContainer组合交互import { createContainer, VictoryZoomContainer, VictoryVoronoiContainer } from 'victory' // 组合 zoom + tooltip const InteractiveContainer = createContainer('zoom', 'voronoi') <VictoryChart containerComponent={ <InteractiveContainer voronoiDimension="x" labels={({ datum }) => `${datum.y}`} /> } > -
主题统一管理
// themes/victory-theme.ts export const customTheme = { axis: { style: { axis: { stroke: '#777' }, ticks: { stroke: '#777' }, tickLabels: { fill: '#333', fontSize: 12 }, }, }, // ... } // 全局使用 <VictoryChart theme={customTheme}> -
React Native 端数据流管理
// 使用 Reanimated SharedValue 确保流畅 function RealtimeChart() { const data = useSharedValue(generateData()) useEffect(() => { const interval = setInterval(() => { data.value = generateData() // 不触发 React 重渲染 }, 100) return () => clearInterval(interval) }, []) return ( <CartesianChart data={data} xKey="x" yKeys={['y']}> {({ points }) => <Line points={points.y} />} </CartesianChart> ) } -
堆叠图表
<VictoryChart> <VictoryStack colorScale="warm"> <VictoryBar data={data1} /> <VictoryBar data={data2} /> <VictoryBar data={data3} /> </VictoryStack> </VictoryChart>
常见陷阱
| 陷阱 | 说明 | 解决方案 |
|---|---|---|
| React Native 迁移 v36→v40+ | 不兼容升级,API 大改 | 参考官方迁移指南,预留充足时间 |
| peer dependencies 遗漏 | RN 端忘记安装 Skia/Reanimated | 文档化安装步骤,CI 检查 |
| Web 端大数据量卡顿 | SVG 节点过多 | 数据降采样或切换 Canvas 方案 |
createContainer 参数顺序 | 组合容器参数顺序影响行为 | 先 zoom 后 voronoi,参考文档 |
| 主题覆盖不完整 | 部分组件样式未受主题控制 | 使用 style prop 补充 |
| Next.js 15 hydration 错误 | v37.3.3 已修复,但需确认版本 | 升级到最新版本 |
技术局限与边界
已知限制
- Web 端仅支持 SVG 渲染:无 Canvas 渲染选项,不适合超大规模数据集
- 社区规模较小:相比 Recharts(900 万周下载量),Victory 的社区资源和教程较少
- React Native 迁移成本高:v36 → v40+ (XL) 是不兼容升级,需安装新依赖并重写部分代码
- Web 端处于维护模式:v37.x 以 bug 修复为主,新功能开发集中在 React Native 端
- 无正式公开路线图:Web 端未来发展方向不明确
- Skia 依赖体积:React Native 端新增 Skia 依赖,显著增加 App 安装包体积
- 图表类型不如 Nivo 丰富:缺少 Sankey、Chord、Heatmap 等高级可视化
不适用场景
- 纯 Web 项目且需要丰富图表类型 → Nivo 更合适
- 需要 Canvas 高性能渲染(Web) → Chart.js / Nivo Canvas
- 快速原型开发 → Recharts 学习曲线更低
- 非 React 项目 → 选择 ECharts / Chart.js / D3
迁移注意事项
- 从 v36 迁移到 v40+ (React Native):这是最大的迁移挑战
- 渲染引擎从 SVG 变为 Skia
- 动画系统从内置变为 Reanimated
- 需要新增三个 peer dependencies
- API 有显著变化,需参考官方迁移指南
- 从 Recharts 迁移到 Victory Web:数据格式兼容,组件 API 需重写
- 从 Victory Web 迁移到 Victory Native XL:API 完全不同,需要重写
- 从 Victory 迁移到其他库:数据层迁移成本低
学习资源
- Victory Web 官方文档:https://commerce.nearform.com/open-source/victory/
- Victory Native 官方文档:https://commerce.nearform.com/open-source/victory-native/docs/
- GitHub 仓库 (Web):https://github.com/FormidableLabs/victory
- GitHub 仓库 (Native XL):https://github.com/FormidableLabs/victory-native-xl
- GitHub Discussions:两个仓库均有活跃的 Discussions 区
- Shopify Engineering Blog:https://shopify.engineering(Skia / Reanimated 技术深度文章)
- Formidable Labs 博客:Victory 设计理念和最佳实践
- YouTube 教程:搜索 "Victory React Native" / "Victory Native XL"
2026 年现状
最新版本
- Web 端:v37.3.6(2025 年 1 月 14 日)— 维护模式
- React Native 端:v41.26.0(2026 年 6 月)— 活跃开发
近期重要更新
Web 端 (v37.x)
| 版本 | 主要变更 |
|---|---|
| v37.3.6 | 修复 zoom 裁剪 bug |
| v37.3.5 | 修复 props.groupComponent 未定义错误 |
| v37.3.4 | 修复 cursor 渲染回归 |
| v37.3.3 | 修复 Next.js 15 hydration 错误、TypeScript 5.7.2 |
| v37.3.0 | Clean Theme 新主题系统 |
| v37.2.0 | Clean theme 应用、delay prop |
React Native 端(Victory Native XL)
活跃开发中,持续发布新版本。v41.26.0(2026 年 6 月)为当前最新版。
发展趋势
- React Native 端是主要方向:Victory 的未来发展重心在 React Native XL
- WebGPU + Skia 生态:Shopify 持续投入 WebGPU + Skia 技术栈,Victory Native XL 直接受益
- Web 端稳定维护:v37.x 保持 bug 修复和类型改进
- 规划中功能(React Native):Windowing/Brushing、Polar Chart Events、Streaming Data、水平柱状图等
- Nearform 维护:项目已从 Formidable Labs 过渡到 Nearform 主要维护
社区活跃度
- Web 端:~11,200 Stars,~440K 周下载量,~84 open issues
- Native 端:~3,500 Stars,活跃 issue 和 Discussions
- Web 端 commit 频率较低(维护模式),Native 端频繁发布
- 2026 年横评文章中仍被推荐为 React Native 图表首选
总体评估
Victory 在 React 图表库生态中的定位清晰且独特:跨平台(Web + React Native)图表方案的首选。Web 端虽处于维护模式但质量稳定,React Native 端(Victory Native XL)基于 Skia 的重写带来了显著的性能提升和光明的技术前景。如果项目需要同时支持 Web 和 React Native 的图表渲染,Victory 几乎是唯一成熟的开源选择。对于纯 Web 项目,需要根据具体需求在 Recharts(简单实用)、Nivo(视觉丰富)和 visx(极致灵活)之间权衡。