为什么数据可视化的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 都给了你创造生产准备、参与和可访问可视化的工具。启动小的、异步的、以及利用丰富的实例生态系统来指导你的旅程。