D3.js 完整详细使用教程(从入门到实战)

发布时间:2026/6/27 4:59:29
D3.js 完整详细使用教程(从入门到实战) 一、D3.js 基础介绍1. 什么是 D3.jsD3Data-Driven Documents数据驱动文档是基于SVG、Canvas、HTML的数据可视化 JS 库核心思想绑定数据 → 操作 DOM把数据映射成图形元素柱状图、折线图、地图、散点图等。2. 优势高度自定义无封装死图表可自由控制每一个图形细节内置强大比例尺、坐标轴、动画、布局、插值、地理计算工具兼容现代浏览器轻量无依赖生态丰富图表、力导向图、热力图、树形图、地图可视化3. 引入 D3方式 1CDN推荐快速上手!-- D3 v7 稳定最新版 -- script srchttps://d3js.org/d3.v7.min.js/script方式 2npm 项目npm install d3import * as d3 from d3二、核心核心概念数据绑定 enter/update/exitD3 灵魂D3 通过select/selectAll选中 DOM用.data()将数组数据和 DOM 元素一一绑定分为三种状态enter数据比 DOM 多 → 新增元素画新图形update数据和 DOM 数量相等 → 更新现有元素修改位置、颜色、尺寸exitDOM 比数据多 → 删除多余元素基础绑定示例svg width400 height200/svg script srchttps://d3js.org/d3.v7.min.js/script script const data [30, 80, 50, 120, 60]; const svg d3.select(svg); // 1. 绑定数据获取三组状态 const rects svg.selectAll(rect) .data(data); // exit多余矩形删除 rects.exit().remove(); // update已有矩形更新属性 rects.attr(x, (d, i) i * 70) .attr(y, d 200 - d) .attr(width, 60) .attr(height, d d) .fill(#4285f4); // enter新增缺失矩形 rects.enter() .append(rect) .attr(x, (d, i) i * 70) .attr(y, d 200 - d) .attr(width, 60) .attr(height, d d) .fill(#4285f4); /script三、D3 基础 API 分类详解1. 选择器 Select操作 DOM// 单选 d3.select(#box) d3.select(.item) d3.select(svg) // 多选返回集合 d3.selectAll(rect) d3.selectAll(.circle) // 链式修改属性/样式/文本 d3.select(rect) .attr(width, 100) // SVG属性 .style(fill, red) // css样式 .text(文字) // 文本内容 .html(b富文本/b)2. 比例尺 Scale可视化核心数据→像素映射原始数据范围域domain→ 画布像素范围范围range1线性比例尺 scaleLinear柱状图 / 折线图数值均匀映射// 数据0~200 映射到画布高度0~180 const yScale d3.scaleLinear() .domain([0, 200]) // 原始数据区间 .range([180, 0]); // 画布区间svg y轴向下倒置 console.log(yScale(100)); // 902序数比例尺 scaleOrdinal分类颜色、分类 X 轴离散分类数据映射const colorScale d3.scaleOrdinal() .domain([苹果, 香蕉, 橙子]) .range([red, yellow, orange]); colorScale(香蕉); // yellow3band 分段比例尺 scaleBand柱状图 X 轴均分自动均分宽度、设置内边距const xData [1月,2月,3月,4月] const xScale d3.scaleBand() .domain(xData) .range([20, 380]) .padding(0.1); // 柱子间距 xScale.bandWidth() // 单根柱子宽度其他常用比例尺scaleLog对数比例尺跨度极大数据scaleTime时间比例尺时间轴折线图scalePow幂等比例尺scaleQuantize分阶比例尺热力图分级3. 坐标轴 Axis自动生成 x/y 轴依赖比例尺自动生成刻度、轴线、文字// 生成x轴渲染函数 const xAxis d3.axisBottom(xScale); // 底部x轴刻度文字朝下 const yAxis d3.axisLeft(yScale); // 左侧y轴 // 在svg中渲染坐标轴 svg.append(g) .attr(transform, translate(0, 200)) // 下移放到底部 .call(xAxis); svg.append(g) .attr(transform, translate(20, 0)) .call(yAxis);transformtranslate(x,y)SVG 平移解决坐标轴偏移问题4. 动画 Transition.transition()实现平滑过渡rects.enter() .append(rect) .attr(height, 0) // 初始高度0 .transition() // 开启动画 .duration(800) // 动画时长ms .delay((d,i)i*100) // 每个柱子延迟错开 .attr(height, dd)5. 数据处理工具 d3-arrayconst data [10,50,30,90]; d3.max(data) // 最大值 90 d3.min(data) // 最小值 10 d3.sum(data) // 总和 d3.mean(data) // 平均值 d3.range(0,10) // [0,1,2...9]四、实战 1完整柱状图可直接复制运行!DOCTYPE html html langzh-CN head meta charsetUTF-8 titleD3 柱状图完整示例/title style svg { border: 1px solid #eee; } /style /head body svg width500 height300/svg script srchttps://d3js.org/d3.v7.min.js/script script // 1. 数据源 const dataset [ {month:1月,value:80}, {month:2月,value:120}, {month:3月,value:60}, {month:4月,value:150}, {month:5月,value:90} ] const width 500; const height 300; const margin {top:20, right:20, bottom:40, left:40}; // 边距 // 画布 总宽高 - 边距 const innerW width - margin.left - margin.right; const innerH height - margin.top - margin.bottom; // 2. 创建svg画布整体右移下移留出边距 const svg d3.select(svg) .attr(width, width) .attr(height, height) .append(g) .attr(transform, translate(${margin.left},${margin.top})); // 3. 创建比例尺 // X轴 band比例尺 const xScale d3.scaleBand() .domain(dataset.map(dd.month)) .range([0, innerW]) .padding(0.15); // Y轴线性比例尺 const yScale d3.scaleLinear() .domain([0, d3.max(dataset, dd.value)]) .range([innerH, 0]); // 4. 坐标轴 const xAxis d3.axisBottom(xScale); const yAxis d3.axisLeft(yScale); // 渲染X轴放在画布底部 svg.append(g) .attr(transform, translate(0,${innerH})) .call(xAxis); // 渲染Y轴 svg.append(g) .call(yAxis); // 5. 绘制柱状图 enter/update/exit const bars svg.selectAll(rect) .data(dataset); bars.exit().remove(); bars.attr(x, dxScale(d.month)) .attr(y, dyScale(d.value)) .attr(width, xScale.bandwidth()) .attr(height, dinnerH - yScale(d.value)) .fill(#3498db); bars.enter() .append(rect) .attr(x, dxScale(d.month)) .attr(width, xScale.bandwidth()) .attr(y, innerH) // 初始在底部 .transition().duration(1000) .attr(y, dyScale(d.value)) .attr(height, dinnerH - yScale(d.value)) .fill(#3498db); /script /body /html五、实战 2折线图时间轴示例svg width600 height300/svg script srchttps://d3js.org/d3.v7.min.js/script script const data [ {date:new Date(2025-01-01), val:20}, {date:new Date(2025-02-01), val:45}, {date:new Date(2025-03-01), val:32}, {date:new Date(2025-04-01), val:60}, {date:new Date(2025-05-01), val:48} ] const margin {t:20, r:20, b:30, l:40}; const w 600 - margin.l - margin.r; const h 300 - margin.t - margin.b; const svg d3.select(svg) .append(g) .attr(transform,translate(${margin.l},${margin.t})); // 时间比例尺 const x d3.scaleTime() .domain(d3.extent(data, dd.date)) .range([0,w]); const y d3.scaleLinear() .domain([0, d3.max(data, dd.val)]) .range([h,0]); // 折线生成器 line const line d3.line() .x(dx(d.date)) .y(dy(d.val)) .curve(d3.curveMonotoneX); // 平滑曲线 // 绘制折线path svg.append(path) .datum(data) // 单组数据绑定用datum .attr(fill,none) .attr(stroke,#e74c3c) .attr(stroke-width,2) .attr(d, line); // 坐标轴 svg.append(g).attr(transform,translate(0,${h})).call(d3.axisBottom(x)); svg.append(g).call(d3.axisLeft(y)); // 圆点标记 svg.selectAll(circle) .data(data) .enter() .append(circle) .attr(cx,dx(d.date)) .attr(cy,dy(d.val)) .attr(r,4) .fill(#e74c3c); /script六、常用布局 Layout复杂图表D3 内置布局函数专门处理复杂图形数据转换只需要传入数据返回图形坐标d3.pie()饼图 / 环形图布局d3.forceSimulation()力导向网络图d3.tree() / d3.hierarchy树形图、组织架构图d3.arc()饼图扇形生成器d3.map/geo地图地理投影饼图极简示例const pieData [10,20,30,40]; const pie d3.pie(); // 饼图布局 const arcs pie(pieData); // 转换为扇形坐标数据 const arc d3.arc() .innerRadius(0) // 内半径大于0就是环形图 .outerRadius(100); svg.selectAll(path) .data(arcs) .enter() .append(path) .attr(d, arc) .fill((d,i)d3.schemeSet2[i]);七、交互鼠标事件、tooltip1. 鼠标监听bars.on(mouseover, function(event, d){ d3.select(this).style(fill,#ff6600); }) .on(mouseout, function(){ d3.select(this).style(fill,#3498db); }) .on(click, (e,d){ console.log(点击数据, d) })2. Tooltip 悬浮提示.tooltip { position:absolute; padding:6px 10px; background:#222; color:#fff; border-radius:4px; pointer-events:none; opacity:0; }div classtooltip/divconst tooltip d3.select(.tooltip); bars.on(mouseover, (e,d){ tooltip.html(数值${d.value}) .style(left, e.pageX px) .style(top, e.pageY - 20 px) .style(opacity,1); }).on(mouseout, (){ tooltip.style(opacity,0) })八、D3 分层开发规范工程化推荐边距模式 margin convention统一预留上下左右边距避免坐标轴被截断上面示例全部使用分离数据、比例尺、坐标轴、图形渲染逻辑图表封装成函数支持传入配置宽高、颜色、数据数据更新只调用一次渲染函数依赖 enter/update/exit 自动 diff样式分离尽量用 class 代替 inline style九、常见踩坑问题SVG y 轴向下比例尺 range 必须倒置 [maxH, 0]否则柱子倒置.data()绑定数组单条数据用.datum()坐标轴需要.call(axis)才能渲染折线 path 使用fill:none否则会填充闭合区域动画 transition 只能写在修改属性前页面缩放模糊svg 设置宽高不要用 css 拉伸十、官方资源 拓展学习官方文档https://d3js.org/官方示例图库https://observablehq.com/d3/gallery海量可编辑可视化案例D3 API 完整手册https://github.com/d3/d3/blob/main/API.md进阶方向地图可视化、3D 结合、Canvas 渲染大数据、交互式大屏十一、扩展练习路线基础柱状图 → 横向柱状图 → 折线图 → 散点图中级饼图 / 环形图、堆叠柱状图、面积图、Tooltip 交互高级树形图、力导向网络图、中国地图、热力图、动态实时更新图表