d3.js通过d3.select()选中真实dom节点(如svg)后用.data()绑定数组数据,再经.enter().append()生成元素;需手动设置svg属性(如cx/cy/r)和比例尺映射坐标,且脚本须在dom就绪后执行。

HTML 元素怎么被 D3.js 选中并绑定数据
D3.js 不是把 HTML “转成” 可视化,而是直接操作现有 DOM 节点。你得先有 <div>、<code><svg></svg> 或其他容器,D3 才能往里塞图形元素。
常见错误是:写了 d3.select("body").data(data).enter().append("circle"),结果页面啥也没出现——因为 不是 SVG 容器,<circle></circle> 必须在 <svg></svg> 内部才有效。
- 必须用
d3.select("svg")或d3.select("#chart")指向一个真实存在的<svg></svg>节点 - 如果 HTML 里没写
<svg></svg>,得先用d3.select("body").append("svg")创建它 -
.data()绑定的是数组,不是单个对象;绑定后要接.enter().append()才生成新元素 - 别对
<p></p>或<div> 直接 append <code><circle></circle>,浏览器会忽略或报错为什么 append("circle") 没显示?坐标和尺寸全靠手动设
D3 不自动设置
cx、cy、r这些 SVG 属性,它们默认为 0 或空字符串,图形就缩成一个点甚至不可见。典型现象:控制台没报错,但页面上什么也看不到;用开发者工具检查发现
<circle></circle>元素存在,但cx="0"、cy="0"、r="0"。- 必须显式调用
.attr("cx", d => d.x)、.attr("cy", d => d.y)、.attr("r", 5) - 数值不能传字符串(比如
"10"),虽然部分浏览器能 coerce,但cx="10px"会失效 - 如果数据里没有
x/y字段,用d => d[0]这类访问方式前,先确认数组结构 - 注意 SVG 坐标系原点在左上角,y 增大是向下,和数学直角坐标系相反
从纯 HTML 到可交互图表:只差一个 .on() 和 scale 函数
静态图形只是起点。真正让 HTML“活起来”的,是 D3 的事件绑定和比例尺——它们不依赖额外框架,但容易漏掉初始化步骤。
比如想点击柱子弹出提示,写了
.on("click", console.log)却没反应:可能因为事件监听器绑在了还没 append 出来的元素上,或者console.log没包函数导致立即执行。-
.on("click", d => alert(d.name))必须写成箭头函数或匿名函数,不能直接写.on("click", alert) - 坐标映射要用
d3.scaleLinear()或d3.scaleBand(),否则数据值直接当像素用,图表会严重失真 - scale 需要提前定义域(
.domain([min, max]))和范围(.range([0, width])),且 domain 必须是数字数组,不能是字符串 - 响应式调整时,别只改
<svg></svg>宽高,记得同步调用scale.range([0, newWidth])并重绘
HTML 中嵌入 D3 图表的最小可行结构
很多人卡在第一步:HTML 页面里到底该放什么?不是越多越好,而是刚好够 D3 启动。
错误做法:把 D3 脚本放在
里,但 DOM 还没加载完,d3.select("#chart")返回 null。- HTML 至少要有:
<div id="chart"></div>,然后 JS 里d3.select("#chart").append("svg") - 脚本标签放
前,或加defer属性,确保 DOM 就绪 - CDN 引入 D3 用
<script src="https://d3js.org/d3.v7.min.js"></script>,v7 默认 ES Module 导出,全局变量是d3 - 别用
import语法写在普通 HTML 里,除非配置了 type="module" 且服务支持 CORS
最麻烦的永远不是语法,是 scale 的 domain 没覆盖全数据,或是 enter/update/exit 逻辑没理清——这两个地方一错,图形要么不更新,要么疯狂重复渲染。
- 必须显式调用











