D3.js
数据驱动文档(Data-Driven Documents)的底层可视化库,用于将数据与 DOM 绑定,基于 SVG、Canvas 和 HTML 创造强大的交互式数据可视化。
D3.js 是 GitHub 星标最高(113k+)的数据可视化库,通过将数据与 DOM 绑定,基于 SVG、Canvas 和 HTML 创造强大的交互式可视化,提供比例尺、布局、形状生成器等完整工具集,灵活性无与伦比。
D3.js
数据驱动文档(Data-Driven Documents)的底层可视化库,用于将数据与 DOM 绑定,基于 SVG、Canvas 和 HTML 创造强大的交互式数据可视化。
技术简介说明
D3.js 全称为 Data-Driven Documents,由 Mike Bostock 于 2011 年在斯坦福大学可视化设计期间创造,是目前 GitHub 上星标最多(113,000+)的数据可视化库。它的核心理念是将数据与 DOM 元素通过声明式绑定(data binding)直接关联,让开发者能够以数据驱动的方式操作文档结构,生成高度定制化的可视化效果。
与大多数开箱即用的高层图表库不同,D3 是一个"元库"(meta-library)——它不提供预设的图表类型,而是提供一套完整的工具集:选择集(selection)、比例尺(scale)、形状生成器(shape generator)、力导向布局(force layout)、地理投影(geo projection)等。开发者通过这些基础模块自由组合,构建任何可以想象的可视化形式。这种底层设计赋予了 D3 无与伦比的灵活性,同时也带来了较高的学习曲线。
自 v6 起,D3 全面转向 ES Modules(ESM),v7 更是要求 Node.js 12+ 并以纯 ESM 形式发布。D3 由 Observable 团队维护,官网品牌为"D3 by Observable",与 Observable Plot(高层快速绘图 API)形成互补:Plot 处理常见图表的快速生成,D3 负责定制化和复杂可视化场景。
基本信息
- 官网:https://d3js.org/
- GitHub:https://github.com/d3/d3
- License:ISC(与 MIT 等效的宽松许可)
- 最新版本:v7.9.0(2024 年 3 月发布)
- 主要维护者/公司:Mike Bostock / Observable, Inc.
- GitHub Stars:~113,000+(2026 年 6 月数据,数据可视化库中最高)
- npm 周下载量:~1,470 万(主包 d3)+ 各子模块单独下载量极高(d3-array 日均约 1,150 万次)
快速上手
安装
# 使用 npm 安装完整 D3 包
npm install d3
# 或使用 yarn
yarn add d3
# 或使用 pnpm
pnpm add d3
# 按需安装单个子模块(推荐用于 tree-shaking)
npm install d3-selection d3-scale d3-shape
# CDN 方式引入(UMD 全局变量)
<script src="https://cdn.jsdelivr.net/npm/d3@7"></script>
# ES Module 方式(推荐)
<script type="module">
import * as d3 from "https://cdn.jsdelivr.net/npm/d3@7/+esm";
</script>基础配置
D3 v7 是纯 ES Module 库,在构建工具中无需额外配置。对于 Vite / Rollup / webpack 5+ 等现代构建工具,直接 import 即可:
// 完整导入
import * as d3 from 'd3'
// 按需导入(减小 bundle 体积)
import { select, selectAll } from 'd3-selection'
import { scaleLinear } from 'd3-scale'
import { line, arc } from 'd3-shape'TypeScript 类型支持:D3 自带 .d.ts 类型声明,无需额外安装 @types/d3。
最小示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>D3 最小示例</title>
<style>
bar { background: steelblue; }
</style>
</head>
<body>
<div id="chart"></div>
<script type="module">
import * as d3 from 'https://cdn.jsdelivr.net/npm/d3@7/+esm'
const data = [30, 86, 168, 281, 303, 365]
const x = d3.scaleLinear()
.domain([0, d3.max(data)])
.range([0, 420])
d3.select('#chart')
.selectAll('div')
.data(data)
.join('div')
.style('width', d => `${x(d)}px`)
.text((d, i) => i)
</script>
</body>
</html>核心概念与架构
模块化架构
D3 采用高度模块化的架构,由 30+ 个独立的 ES 子模块组成,每个模块职责单一、可独立使用:
d3(完整包)
├── d3-selection — DOM 选择集与数据绑定(核心)
├── d3-transition — 基于选择集的动画过渡
├── d3-scale — 比例尺:线性、序数、时间、对数等
├── d3-scale-chromatic — 颜色方案与插值器
├── d3-shape — 形状生成器:线、弧、面积等
├── d3-array — 数组统计与操作工具
├── d3-axis — 坐标轴组件
├── d3-color — 颜色空间(RGB、HSL、Lab 等)
├── d3-interpolate — 值插值(数字、颜色、对象)
├── d3-time — 时间计算工具
├── d3-time-format — 时间格式化与解析
├── d3-format — 数字格式化
├── d3-quadtree — 四叉树空间索引
├── d3-geo — 地理投影与球面几何
├── d3-path — SVG Path 序列化
├── d3-polygon — 多边形几何工具
├── d3-random — 随机数生成器
├── d3-force — 力导向模拟布局
├── d3-hierarchy — 层次数据结构(树、集群、打包等)
├── d3-contour — 等值线/密度等高线
├── d3-delaunay — Delaunay 三角剖分 / Voronoi 图
├── d3-chord — 弦图布局
├── d3-sankey — 桑基图布局(第三方扩展)
├── d3-zoom — 缩放与平移交互
├── d3-drag — 拖拽交互
├── d3-brush — 框选交互
├── d3-fetch — 数据加载(CSV、JSON、XML 等)
├── d3-timer — 高效定时器(requestAnimationFrame 封装)
└── d3-dispatch — 事件分发系统
核心工作原理
1. 选择集(Selection) D3 的核心是选择集机制,通过 CSS 选择器选中 DOM 元素并赋予数据绑定能力:
const circles = svg.selectAll('circle')
.data(dataset) // 数据绑定
.join('circle') // enter + update + exit 一体化
.attr('r', d => d.value)
.attr('fill', 'steelblue')2. Enter-Update-Exit 模式 这是 D3 最核心的数据驱动范式。当数据与 DOM 绑定时:
- Enter:数据多于 DOM 元素 → 创建新元素
- Update:数据与已有元素对应 → 更新属性
- Exit:DOM 元素多于数据 → 移除多余元素
selection.join() 是 v5+ 推荐的简化写法,内部自动处理 enter/update/exit。
3. 比例尺(Scale) 比例尺是数据域(domain)到视觉范围(range)的映射函数,是连接数据与视觉的桥梁:
// 线性比例尺
const x = d3.scaleLinear()
.domain([0, 100]) // 数据域
.range([0, 500]) // 像素范围
x(50) // → 2504. 渲染无关性 D3 的形状生成器、比例尺、统计函数等都是纯计算函数,不直接操作 DOM。这意味着它们可以与 SVG、Canvas、WebGL 甚至服务器端渲染配合使用。
核心特性
- 无与伦比的灵活性:D3 不提供预设图表,而是提供构建任何可视化所需的基础工具,适合完全定制化的视觉设计
- 数据驱动 DOM 操作:通过选择集和数据绑定,以声明式方式将数据映射到 DOM 属性,天然适合响应式数据变化
- 模块化与 Tree-shaking:30+ 独立子模块可按需导入,现代构建工具可自动剔除未使用代码
- 丰富的数学与统计工具:内置数组统计、随机数生成、几何计算、力导向模拟等,是数据处理和可视化的瑞士军刀
- 完整的交互系统:内置 zoom(缩放)、drag(拖拽)、brush(框选)等交互行为,可组合出复杂的交互可视化
- SVG + Canvas + HTML 多渲染目标:同一套数据逻辑可输出到 SVG(DOM 可访问)、Canvas(高性能)或 HTML 元素
- 地理可视化支持:d3-geo 提供完整的地图投影系统,支持 TopoJSON/GeoJSON,可绘制复杂的世界地图和地理热力图
- 力导向布局:d3-force 提供物理模拟引擎,适合节点-链接图、网络图、气泡图等
- 层次数据布局:d3-hierarchy 支持树图、treemap、sunburst、circle-packing 等多种层次数据可视化
- 活跃且庞大的社区:113K+ GitHub Stars,Observable 平台上有大量公开的 D3 可视化作品可供学习
生态图
关键依赖
D3 本身是零依赖的纯 JavaScript 库,仅依赖原生 Web API(DOM、Canvas、SVG)。各子模块之间的依赖关系是明确的,例如:
d3-axis依赖d3-selection、d3-scale、d3-formatd3-shape依赖d3-pathd3-transition依赖d3-selection、d3-interpolate、d3-timer
上层封装库
由于 D3 学习曲线陡峭,社区衍生出大量基于 D3 的高层封装库:
| 库名 | 定位 | 说明 |
|---|---|---|
| Observable Plot | 高层快速绘图 | D3 官方团队开发,声明式 API,快速生成分布图、折线图、热力图等 |
| Vega / Vega-Lite | 声明式可视化语法 | 用 JSON 语法描述可视化,底层可用 D3 渲染 |
| Nivo | React 图表库 | 基于 D3 的 React 图表组件集,提供丰富的预设图表类型 |
| Victory | React/Victory 图表 | Formidable 开发,D3 驱动,支持 React 和 React Native |
| Recharts | React 图表库 | 基于 D3 的声明式 React 图表,API 简洁 |
| C3.js | D3 预设图表 | 可复用的 D3 图表组件,API 类似 Highcharts |
| ** Billboard.js** | C3.js 继任者 | C3.js 的社区分支,更活跃的维护和更新 |
| d3-tip | 工具提示 | D3 专用的 tooltip 扩展库 |
| d3-scale-chromatic | 颜色方案 | 包含所有 ColorBrewer 和 viridis 颜色方案 |
社区生态
- ObservableHQ:D3 作者 Mike Bostock 创建的交互式数据科学平台,是学习和分享 D3 可视化的首选平台
- Block Builder:社区用户构建的 D3 可视化画廊(bl.ocks.org 遗产)
- D3 Graph Gallery:法国统计师 Yan Holtz 维护的 D3 图表示例库
- d3-gallery(GitHub):社区收集的 D3 可视化案例
- R/Python 集成:通过 htmlwidgets 或 IPython 嵌入,D3 可在 R Markdown 和 Jupyter 中使用
适用场景
- 高度定制化数据可视化:当标准图表库无法满足独特的视觉设计需求时,D3 是唯一能提供完全控制力的选择。适合品牌定制可视化、艺术化数据展示。
- 交互式探索仪表板:结合 zoom、brush、drag 等交互原语,D3 可以构建支持缩放、框选、联动的高交互数据探索界面,适合数据分析师和科研人员。
- 复杂网络图与关系图:利用 d3-force 力导向布局,适合构建社交网络图、知识图谱、组织架构、依赖关系图等节点-链接型可视化。
- 地理信息系统(GIS)可视化:d3-geo 模块提供完整的地图投影系统,支持 TopoJSON/GeoJSON 数据格式,适合构建自定义地图、热力地图、航线图等。
- 层次数据可视化:d3-hierarchy 支持 treemap、sunburst、circle-packing 等,适合展示文件目录、组织结构、分类体系等层次数据。
- 数据新闻与信息图:纽约时报、The Pudding 等数据新闻机构的标志性可视化作品大多基于 D3,适合讲述数据故事的复杂信息图。
- 科学研究与数据探索:在 Observable 笔记本中,D3 是科学计算和数据探索的标准工具,适合快速实验性可视化。
开发与工程化
开发流程
# 克隆 D3 源码(用于开发或贡献)
git clone https://github.com/d3/d3.git
cd d3
# 安装依赖
pnpm install
# 运行测试
pnpm test
# 构建
pnpm rollup -c在 React / Vue / Svelte 中使用
D3 操作 DOM 的方式与 React/Vue 的虚拟 DOM 冲突,需要小心集成:
React 集成策略:
// 方式一:仅使用 D3 的计算模块,React 负责渲染
import { scaleLinear } from 'd3-scale'
import { line } from 'd3-shape'
function LineChart({ data, width, height }) {
const x = scaleLinear().domain([0, 100]).range([0, width])
const y = scaleLinear().domain([0, 100]).range([height, 0])
const path = line().x(d => x(d.x)).y(d => y(d.y))(data)
return <svg><path d={path} /></svg>
}
// 方式二:使用 ref 让 D3 直接操作特定 DOM 子树
function ForceGraph({ nodes }) {
const svgRef = useRef()
useEffect(() => {
const svg = d3.select(svgRef.current)
// ... D3 操作
}, [nodes])
return <svg ref={svgRef} />
}Vue 集成策略:类似 React,优先使用 D3 的纯计算模块(scale、shape、array),在 onMounted 中用 useRef 或 ref 获取 DOM 节点供 D3 操作。
Svelte 集成:Svelte 与 D3 的兼容性最好——Svelte 直接操作 DOM,与 D3 的选择集理念一致。
构建与部署
- D3 子模块均发布在 npm,构建工具(Vite / webpack / Rollup)原生支持
- 纯 ESM 发布,不支持 CommonJS require(v7+),需要
async import或构建工具转换 - CDN 部署:
https://cdn.jsdelivr.net/npm/d3@7或https://unpkg.com/d3@7 - 推荐按需导入子模块,避免全量打包
CI/CD 集成
D3 本身是纯客户端库,CI/CD 只需确保:
- Node.js ≥ 12(v7 要求)
- 单元测试使用 jsdom 或 happy-dom 提供 DOM 环境
- 视觉回归测试使用 Playwright / Puppeteer 截图对比
性能与安全
性能特点
- SVG 渲染:适合中小规模数据(< 1000 个元素),每个元素是独立 DOM 节点,可通过 CSS 样式控制,但大量元素时 DOM 操作开销大
- Canvas 渲染:D3 支持 Canvas 渲染(通过 d3-path + Canvas API),适合大规模数据(10,000+ 点),性能远优于 SVG
- d3-force 布局计算:力导向模拟的计算复杂度为 O(n²),节点数超过 1,000 时需使用四叉树近似(
forceManyBody().theta())或 Web Worker - d3-delaunay:Delaunay 三角剖分性能极高,适合最近点查询和 Voronoi 交互区域划分
- 内存使用:D3 本身内存占用低,但大量 SVG 元素会导致浏览器内存压力
优化建议
- 数据量大时(> 1000 点),优先使用 Canvas 而非 SVG
- 使用
d3-quadtree进行空间索引,避免 O(n²) 的碰撞检测 - 使用 Web Worker 进行 d3-force 布局的后台计算
- 使用
requestAnimationFrame(d3-timer)控制渲染频率 - 对静态元素使用
will-change: transformCSS 提示浏览器合成层优化 - 使用
d3.zoom的extent和scaleExtent限制缩放范围,避免极端缩放导致的渲染问题
安全注意事项
- XSS 风险:使用
selection.html()而非selection.text()时,若数据包含用户输入,可能导致 XSS 攻击。务必对用户输入进行转义 - CDN 完整性:使用 CDN 引入 D3 时,应添加 SRI(Subresource Integrity)hash 防止供应链攻击
- eval 风险:避免在 D3 代码中使用动态生成的函数体(如
new Function())
技术对比
D3.js vs Chart.js vs ECharts
| 对比维度 | D3.js | Chart.js | Apache ECharts |
|---|---|---|---|
| 定位 | 底层数据操作与可视化引擎 | 简单易用的图表库 | 功能丰富的商业级图表库 |
| 学习曲线 | 陡峭(需理解选择集、比例尺、布局) | 平缓(配置式 API) | 中等(配置项多但有文档) |
| 渲染方式 | SVG / Canvas / HTML 可选 | Canvas | Canvas(大数据集)/ SVG |
| Bundle 大小 | 全量 ~90KB gzipped,按需可至 ~10KB | ~65KB gzipped | ~400KB gzipped |
| 灵活性 | 极高(可创造任何可视化) | 低(仅限预设图表类型) | 中(丰富预设但难完全定制) |
| 内置图表类型 | 无(需手工构建) | 8 种(bar、line、pie 等) | 20+ 种 |
| 交互能力 | 可完全自定义 | 内置 tooltip、legend、zoom | 内置丰富交互 |
| 适用数据规模 | 小到大(Canvas 模式) | 小到中 | 中到大(百万级数据点) |
| React/Vue 集成 | 需小心处理 DOM 冲突 | 有官方 react-chartjs-2 等封装 | 有 vue-echarts 等封装 |
| GitHub Stars | ~113,000 | ~67,000 | ~62,000 |
| npm 周下载量 | ~1,470 万 | ~240-1000 万 | ~800 万 |
D3.js vs Observable Plot
| 对比维度 | D3.js | Observable Plot |
|---|---|---|
| 定位 | 底层工具集 | 高层声明式图表 API |
| API 风格 | 命令式、链式 | 声明式、标记(mark)驱动 |
| 学习曲线 | 陡峭 | 平缓 |
| 适用场景 | 完全定制化可视化 | 快速 EDA 和标准图表 |
| 底层关系 | — | 基于 D3 构建 |
最佳实践
生产环境最佳实践
1. 按需导入,控制 bundle 体积
// ❌ 避免全量导入
import * as d3 from 'd3'
// ✅ 按需导入子模块
import { scaleLinear, extent } from 'd3'
// 或更细粒度
import { scaleLinear } from 'd3-scale'
import { extent } from 'd3-array'2. 使用 join() 替代手动 enter/update/exit
// ❌ 旧式写法
const circles = svg.selectAll('circle').data(data)
circles.enter().append('circle')
circles.exit().remove()
// ✅ 推荐写法
svg.selectAll('circle')
.data(data)
.join('circle')
.attr('r', d => d.value)3. 将比例尺和布局逻辑与渲染分离
// 纯计算逻辑可测试、可复用
const computeLayout = (data, width, height) => {
const x = d3.scaleLinear().domain(d3.extent(data, d => d.x)).range([0, width])
const y = d3.scaleLinear().domain(d3.extent(data, d => d.y)).range([height, 0])
return { x, y }
}
// 渲染逻辑单独处理
const render = (svg, data, scales) => { ... }4. 过渡动画使用 .transition() 但注意性能
// 少量元素可自由使用过渡
circles.transition().duration(750)
.attr('r', d => d.value)
// 大量元素避免过渡,直接设置属性5. 为 Canvas 渲染使用 d3-path
const path = d3.path()
d3.line().context(path)(data)
canvasContext.beginPath()
canvasContext.fillStyle = 'steelblue'
new Function(path)() // 或直接使用 Path2D
canvasContext.fill()常见陷阱
- DOM 冲突:在 React/Vue 中使用 D3 时,避免让 D3 操作虚拟 DOM 管理的节点。使用
useRef/ref隔离 D3 操作范围 - 全量导入:
import * as d3 from 'd3'会打包全部模块(~90KB gzipped),按需导入可减至 10-20KB - 内存泄漏:在 React
useEffect中创建的 D3 定时器、事件监听器需在清理函数中销毁 - 比例尺域错误:
d3.scaleLinear()的 domain 和 range 长度必须一致,否则行为未定义 - force simulation 未停止:
d3.forceSimulation()会持续运行,需在组件卸载时调用simulation.stop()
技术局限与边界
已知限制
- 学习曲线极陡峭:D3 的选择集、数据绑定、Enter-Update-Exit 模式需要时间掌握。新手通常需要数周才能产出复杂可视化
- 不提供预设图表:D3 不会帮你画一个"柱状图"——你需要自己创建 SVG 元素、计算位置、绘制坐标轴。这意味着开发一个简单柱状图的代码量远大于 Chart.js
- 纯 ESM 限制:v7 起不再支持 CommonJS
require(),需要旧版 Node.js 或构建工具支持 - SVG 性能天花板:大量 SVG 元素(> 1000)会导致浏览器重排/重绘缓慢,必须切换到 Canvas 渲染或使用 WebGL
- 服务端渲染复杂:D3 深度依赖 DOM API,服务端渲染需要 jsdom 模拟完整 DOM 环境,性能和完整性受限
- 移动端手势支持弱:D3 的 zoom/drag 基于 Pointer Events,移动端体验不如专门的触摸手势库
- 无内置响应式:D3 不提供容器尺寸监听,需要手动使用
ResizeObserver实现响应式图表 - 调试困难:链式调用和函数式风格使错误栈难以追踪,初学者调试成本高
不适用场景
- 简单的业务后台图表 → 使用 Chart.js 或 ECharts 更高效
- 需要快速原型验证 → Observable Plot 或 ECharts 更合适
- 团队可视化经验不足 → D3 学习投入产出比不划算
- 需要实时流数据图表 → 考虑 uPlot、LightningChart 等专注实时场景的库
- 大规模数据(> 100 万点)→ 考虑 WebGL 方案(deck.gl、regl)或专业库(LightningChart)
迁移注意事项
- D3 v7 到未来 v8 可能的变化:ESM-only 已确立,关注 Node.js 最低版本要求
- 从 D3 v6 迁移到 v7 的主要变化:
d3.selection的 iterables 支持改进,d3.force的随机种子变化 - 从 D3 v5 迁移到 v6+:Promise-based API(移除 d3-request),事件参数变化
学习资源
- 官方文档:https://d3js.org/(含 Getting Started、What is D3、模块文档)
- D3 API 参考:https://github.com/d3/d3/blob/main/API.md(完整 API 列表与模块链接)
- Observable 平台:https://observablehq.com/@d3(Mike Bostock 的官方 D3 笔记本集,最佳学习资源)
- 书籍:《D3.js in Action》(第三版,2019)、《Learning D3.js》(Packt,2023)
- 教程:
- D3 Graph Gallery:https://www.d3-graph-gallery.com/(按图表类型索引的 D3 示例)
- Observable 教程:https://observablehq.com/tutorial
- Curran Kelleher 的 D3 课程(YouTube)
- 中文文档:https://d3js.cn/、https://d3.nodejs.cn/
- 社区:
- Observable 论坛:https://talk.observablehq.com/
- Reddit:r/d3js
- Stack Overflow:[d3.js] 标签
- GitHub Discussions:https://github.com/d3/d3/discussions
2026 年现状
版本与活跃度
- 最新稳定版:v7.9.0(2024 年 3 月发布),v7 系列最后一次更新
- GitHub Stars:~113,000+(2026 年 6 月),持续增长,是 GitHub 上星标最多的数据可视化库
- 最后代码提交:2025 年 12 月(仓库活跃度正常,以依赖更新和小修复为主)
- npm 周下载量:主包约 1,470 万次,各子模块合计更高
发展趋势
- 维护状态:D3 进入稳定维护期,无重大功能版本计划。v8 尚无公开路线图
- Observable Plot 互补:Observable 团队将更多新特性投入到 Observable Plot(高层 API),D3 核心库趋于稳定
- 社区热度:D3 在 2025 JavaScript Rising Stars 中仍名列前茅,作为底层库的地位稳固
- 生态扩展:d3-sankey、d3-hexbin 等社区扩展保持活跃;Observable 平台持续产出 D3 教程和示例
- AI 集成:社区出现 AI 辅助生成 D3 代码的工具(如 Observable 的 AI 功能),降低学习门槛
未来展望
D3 作为数据可视化领域的基础设施,其地位在可预见的未来不会被动摇。虽然高层库(ECharts、Chart.js、Observable Plot)持续分流简单场景的用户,但在定制化、复杂可视化、数据新闻、科研探索等领域,D3 仍然是不可替代的首选工具。2026 年的 D3 生态以稳定为主,核心库保持低频更新,社区和上层库(Observable Plot)是主要创新阵地。