Table of Contents
为什么数据可视化的D3.js
数据可视化可以弥合原始数字与人类理解之间的差距。在很多可用的工具中,D3.js(Data-Driven Documents)是一个多功能的低层JavaScript库,它让开发者直接控制文档对象模型(DOM),与提供有限定制的高层次图表库不同,D3允许您精确地描述您所需要的视觉表现——从简单的条形图到复杂的地理图和网络图,其数据约束模型确保您数据集的任何变化自动更新视觉要素,使其成为交互仪表板和探索性数据分析的理想. D3被主要组织用于灵活,性能,以及处理各种数据格式的能力.
D3.js的核心概念
要有效地利用 D3 , 您必须理解其基础原理: 选择、 数据绑定、 缩放和 SVG。 D3 操作时会选择 DOM 元素, 将数据绑定在它们身上, 并应用转换。 这个模式是通过方法链来表达的, 最好用一个简单的例子来说明 。
选择和数据绑定
D3 使用 CSS 选择器来瞄准元素, 然后将数据附加到它们上。 [[FLT: 0] 方法将一组数值与选定的节点结合, 方法为缺少相应的 DOM 节点的任何数据点创建了新的元素。 这种输入式的上调- 退出模式允许您高效地处理动态数据集 。
例如,要创建数据集的圆圈:
const data = [10, 25, 40, 30];
const svg = d3.select("body").append("svg")
.attr("width", 400)
.attr("height", 200);
svg.selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("cx", (d, i) => i * 100 + 50)
.attr("cy", 100)
.attr("r", d => d)
.attr("fill", "steelblue");
缩放和轴
原始数据通常跨度不直接映射到像素坐标的范围. D3 提供了 比例尺,将域(数据值)映射到一个范围(像素位置). 常见的尺度包括,,以及[]. 轴然后使用或生成. 各种尺度和轴共同构成任何定量可视化的基础.
线性尺度示例:
const xScale = d3.scaleLinear()
.domain([0, d3.max(data)])
.range([0, width]);
const yScale = d3.scaleLinear()
.domain([0, d3.max(data)])
.range([height, 0]);
const xAxis = d3.axisBottom(xScale);
svg.append("g")
.attr("transform", `translate(0, ${height})`)
.call(xAxis);
与 D3. js 建立交互式视觉
交互将静态图表转换为可扩展的故事。 D3 支持事件处理器、 转换和动态更新。 您可以添加工具提示、 缩放、 拖放、 过滤和动画, 并且最小的上方。 下面我们扩展工具提示并引入其他常见的交互功能 。
工具提示和突出显示
工具提示提供了悬浮的精确数据值。 使用 D3 事件系统, 您可以创建一个显示细节的浮动 [[ FLT: 9] 。 例如, 带工具提示的列图扩展在原始代码中已经显示; 在此我们还添加了 [ [ [ FLT: 0]] 颜色变化 [[ [FLT: 1]] :
svg.selectAll("rect")
.data(data)
.enter()
.append("rect")
.attr("x", (d, i) => i * 70)
.attr("y", d => height - d * 3)
.attr("width", 50)
.attr("height", d => d * 3)
.attr("fill", "steelblue")
.on("mouseover", function(event, d) {
d3.select(this).attr("fill", "orange");
tooltip.style("display", "block").text(`Value: ${d}`);
})
.on("mousemove", (event) => {
tooltip.style("left", (event.pageX + 10) + "px")
.style("top", (event.pageY - 20) + "px");
})
.on("mouseout", function() {
d3.select(this).attr("fill", "steelblue");
tooltip.style("display", "none");
});
缩放和泛
对于大型数据集或时间序列数据,缩放和平面帮助用户聚焦于感兴趣的区域. D3's ]的行为会改变坐标系统。应用到包含您视觉元素的SVG组中.
const zoom = d3.zoom()
.scaleExtent([1, 10])
.on("zoom", (event) => {
g.attr("transform", event.transform);
});
svg.call(zoom);
动态数据更新
交互式仪表板通常需要刷新数据而不重新加载页面. D3 更新模式优雅地处理添加,删除,修改元素. 关键是重新运行与新数据的结合,并使用 的额外节点.
function updateData(newData) {
const circles = svg.selectAll("circle").data(newData);
circles.exit().remove(); // remove old
circles.enter().append("circle") // add new
.merge(circles) // merge with existing
.attr("cx", (d, i) => i * 100 + 50)
.attr("cy", 100)
.attr("r", d => d);
}
高级 D3 技术
版图和地理可视化
D3 包括用于复杂图表的专门布局模块: 创建派/射线数据, 模拟物理用于网络图表, ] 项目地图数据使用 GeoJSON。 这些模块大幅削减了精密可视化所需的代码。 例如,创建了强制引导的网络 :
const simulation = d3.forceSimulation(nodes)
.force("link", d3.forceLink(links))
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, height / 2));
过渡和动画
平滑的转换可以改善用户体验。 D3 的 [[FLT: 19]] 动画会随时间变化而改变属性。 您可以控制持续时间、 放松和延迟。 例如, 动画条会增长 :
svg.selectAll("rect")
.data(data)
.enter()
.append("rect")
.attr("x", (d, i) => i * 70)
.attr("y", height)
.attr("width", 50)
.attr("height", 0)
.attr("fill", "steelblue")
.transition()
.duration(800)
.ease(d3.easeBounce)
.attr("y", d => height - d * 3)
.attr("height", d => d * 3);
生产最佳做法-准备D3
性能优化
对于大型数据集(千点),直接DOM操作变得缓慢. 使用canvas[]通过D3-canvas或考虑]与jacle.gl等库进行渲染.gl. WebGL[. 对于基于SVG的视觉,通过使用组来降低DOM的复杂性,并避免在每个帧上更新每个元素. 使用[debunted 事件处理器和缓存选择器.
无障碍和反应
可视化应该被所有用户所察觉。在 SVG 元素上提供] 标记,使用 ARIA 属性,并包括一个文本表作为倒置。对于响应性设计,将 SVG 维度以容器宽度为基础,使用 并听用 D3 修改窗口大小的事件。
function resize() {
const width = container.node().getBoundingClientRect().width;
svg.attr("width", width)
.attr("height", width * aspectRatio);
// redraw scales and axes
}
window.addEventListener("resize", resize);
代码组织
即使在单页应用程序中,您也可以将您的 D3 代码构建为模块: 一个用于数据获取, 一个用于缩放/轴, 一个用于绘图, 一个用于交互。 使用 ES6 模块或 Webpack 这样的捆绑器。 避免将 D3 逻辑直接与框架生命周期钩混合; 相反, 创建一个您框架调用的 D3 类。
将D3与现代框架相结合
反射、角射和Vue管理自己的DOM。为了避免冲突,只使用D3来进行计算(比例、形状),让框架制成SVG。或者,使用像 或 这样的专用包装器。然而,为了完全控制,您仍可以在 (反应)或 (Angular) 中使用D3,并使用根元素参考。这保持了D3高效的更新周期与框架重报的分离。
真实世界实例和使用案例
D3赋予许多高知名度的可视化项目:在可观测上的D3 Gallery显示数百个实例,从动画配音到交互时间段. 纽约时报等新闻组织使用D3来进行自定义的数据故事. 在企业设置中,D3启用了财务数据或实时IOT传感器接口的自定义仪表板,其灵活性意味着您可以将多个图表类型组合成一个单一的凝聚界面.
示例: 交互式散块绘图, 带有工具提示和Brushing
想象一个有500个点的数据集,其中包含x,y,和分类。使用D3,您可以创建一个以类别为颜色的圆圈的散点图,一个显示准确坐标的工具提示,以及一个突出选定点的刷子。代码结构遵循上面的规律。刷子交互将看起来像:
const brush = d3.brush()
.extent([[0, 0], [width, height]])
.on("brush end", brushed);
svg.append("g").call(brush);
function brushed(event) {
if (event.selection) {
const [[x0, y0], [x1, y1]] = event.selection;
circles.classed("selected", d =>
x0 <= xScale(d.x) && xScale(d.x) <= x1 &&
y0 <= yScale(d.y) && yScale(d.y) <= y1
);
} else {
circles.classed("selected", false);
}
}
学习资源和下一步
用于主控 D3 , 请从官方 [ [FLT: 0]] D3. js 文档 [[FLT: 1] 和 [[FLT: 2] 上的自由导师 。 通过可观察笔记本工作, 提供您可以叉的活代码 。 另外, 读 [[[FLT: 4]] 的 Scott Murray [[FLT: 5] 的“ 网络交互数据可视化 ” , 以便进行透彻的介绍 。 将经典图表( 栏、 线、 散) 从头重刻, 添加交互性 。 用于树图的实验 [[FLT: 30] 或用于地图的实验 [[FLT: 31]] 。
结论
D3.js 仍然是网络上自定义交互数据可视化的金本位。 它的陡峭的学习曲线被无法匹配的灵活性、性能和社区支持所抵消。 通过掌握其核心概念 — — 选择、数据约束、尺度和事件处理 — — 你可以构建可视化,将数据转化为洞察力。无论是在构建简单的条形图还是复杂的多视图仪表板,D3 都给了你创造生产准备、参与和可访问可视化的工具。启动小的、异步的、以及利用丰富的实例生态系统来指导你的旅程。