牛旦教育翻译,译者:山野
英文链接:https://d3js.org/
1 导引
D3.js是一个基于文档的数据操作JavaScript库。D3能帮助你使用HTML、SVG和CSS而使数据生动起来。D3对web标准的强化为你提供了现代浏览器的全部功能,而无需将自己捆绑在专有框架上,还结合了强大的可视化组件和数据驱动的DOM操作方法。
在此下载最新版本(6.1.1):
d3.zip: https://github.com/d3/d3/releases/download/v6.1.1/d3.zip
要直接链接到最新版本,请复制如下片段:
完整的源代码和测试也可以在GitHub上下载:https://github.com/d3/d3。
2 简介
D3允许您将任意数据绑定到文档对象模型(DOM),然后对文档应用数据驱动的转换。例如,可以使用D3从一组数字生成HTML表。或者,使用相同的数据创建具有平滑转换和交互的交互式SVG条形图。
D3不是一个试图提供所有可能的特性的单一框架。相反,D3解决了问题的关键:基于文档有效地操作数据。这避免了专有表示,并提供了非凡的灵活性,D3公开了HTML、SVG和CSS等web标准的全部功能。D3耗费最小的开销,却提供非常快的速度,并支持大数据集和动态行为的交互和动画。D3的功能风格允许利用各种官方(https://github.com/d3/d3/blob/master/API.md)和社区(https://www.npmjs.com/browse/keyword/d3-module)开发的模块而重用代码。
3 选择(Selections)
使用W3C DOM API(https://www.w3.org/DOM/DOMTR)修改文档很繁琐:方法名很冗长,命令式方法需要手动迭代和临时状态的记录。例如,改变段落元素的文本颜色:
var paragraphs = document.getElementsByTagName("p");for (var i = 0; i < paragraphs.length; i++) { var paragraph = paragraphs.item(i); paragraph.style.setProperty("color", "blue", null);}
D3采用了一种声明性方法,对称为selections的任意节点集进行操作。例如,你可以重写上面的循环为:
d3.selectAll("p").style("color", "blue");
然而,您仍然可以根据需要操作单个节点:
d3.select("body").style("background-color", "black");
选择器是由W3C Selectors API(https://www.w3.org/TR/selectors-api/)定义的,并被现代浏览器原生支持。上面的示例根据标签名称(分别为“p”和“body”)选择节点。可以使用各种谓词选择元素,包括包含、属性值、类和ID。
D3提供了许多改变节点的方法:设置属性或样式;注册事件侦听器;添加、删除或排序节点;以及更改HTML或文本内容。这些足以满足绝大多数的需要。直接访问底层DOM也是可能的,因为每个D3 selection只是一个节点数组。
更多关于Selection信息,请访问:https://github.com/d3/d3-selection
4 动态特性
熟悉其他DOM框架(如jQuery)的读者应该能立即识别出与D3的相似之处。但是样式、属性和其他属性可以在D3中指定为数据函数,而不仅仅是简单的常量。尽管它们表面上很简单,但这些功能可能非常强大;例如,d3.geoPath函数将地理坐标投影到SVG路径数据中。D3提供了许多内置的可重用函数和函数工厂,比如用于区域图、线形图和饼形图的图形原语。
例如,对段落随机着色:
d3.selectAll("p").style("color", function() { return "hsl(" + Math.random() * 360 + ",100%,50%)";});
对偶数和奇数节点的灰色阴影的交替:
d3.selectAll("p").style("color", function(d, i) { return i % 2 ? "#fff" : "#eee";});
计算属性通常引用绑定数据。Data被指定为一个值数组,每个值作为第一个参数(d)传递给选择函数。使用默认的按索引连接(join-by-index),数据数组中的第一个元素被传递给选择中的第一个节点,第二个元素传递给第二个节点,依此类推。例如,如果你绑定一个数字数组到段落元素,你可以使用这些数字来计算动态字体大小:
d3.selectAll("p") .data([4, 8, 15, 16, 23, 42]) .style("font-size", function(d) { return d + "px"; });
一旦数据被绑定到文档,就可以省略数据操作符;D3将检索之前绑定的数据。这允许您无需重新绑定就可以重新计算属性。
更多数据连接,请查阅:https://bost.ocks.org/mike/join/
5 进入与退出
使用D3的enter和exit选择(selections),您可以为传入数据创建新节点,并删除不再需要的传出节点。
当数据被绑定到一个selection时,数据数组中的每个元素将与选择中的相应节点配对。如果节点比数据少,那么额外的数据元素将形成输入选择(enter selection),您可以通过追加到输入选择来实例化该选择。例如:
d3.select("body") .selectAll("p") .data([4, 8, 15, 16, 23, 42]) .enter().append("p") .text(function(d) { return "I’m number " + d + "!"; });
更新节点是默认选择—数据操作符的结果。因此,如果您忘记了输入和退出选择(enter 和 exit selections),那么您将自动只选择存在相应数据的元素。一种常见的模式是将初始选择分解为三个部分:要修改的更新节点、要添加的输入节点和要删除的退出节点。
// Update…var p = d3.select("body") .selectAll("p") .data([4, 8, 15, 16, 23, 42]) .text(function(d) { return d; }); // Enter…p.enter().append("p") .text(function(d) { return d; }); // Exit…p.exit().remove();
通过分别处理这三种情况,可以精确地指定哪些操作在哪些节点上运行。这提高了性能,并对转换提供了更好的控制。例如,对于条形图,您可以使用旧的标度(scale)来初始化输入条,然后将输入条与更新和退出的条一起转换到新的标度。
D3让你基于数据转换文档;这包括创建和销毁元素。D3允许您更改现有文档以响应用户交互、随时间变化的动画,甚至来自第三方的异步通知。甚至还有一种混合方法,其中文档最初在服务器上呈现,然后通过D3在客户机上更新。
6 转换,不是表现
D3没有引入新的可视化表现。与Processing或Protovis不同,D3 的图形标记词汇表直接来自web标准:HTML、SVG和CSS。例如,您可以使用D3创建SVG元素,并使用外部样式表对其进行样式设置。您可以使用复合滤镜效果、虚线笔画和剪切。如果浏览器厂商明天引入新特性,您将能够立即使用它们,而不需要工具包更新。而且,如果您决定在将来使用D3以外的工具集,那么您可以随身携带有关标准的知识!
最重要的是,使用浏览器的内置元素检查器,D3很容易调试:使用D3操作的节点正是浏览器本身可以理解的节点。
7 转换
D3对转换的关注自然扩展到动画过渡。过渡会随着时间的推移逐渐插入样式和属性。渐变可以通过“弹性”、“立方进出”和“线性”等放松功能来控制。D3的插值器(interpolators)既支持原语,比如数字和嵌入在字符串中的数字(字体大小、路径数据等),也支持复合值。您甚至可以扩展D3的插值器注册表来支持复杂的属性和数据结构。
例如,将页面背景淡入黑色:
d3.select("body").transition() .style("background-color", "black");
或者,用交错延迟调整符号映射中的圆的大小:
d3.selectAll("circle").transition() .duration(750) .delay(function(d, i) { return i * 10; }) .attr("r", function(d) { return Math.sqrt(d * scale); });
通过只修改实际发生变化的属性,D3减少了开销,并在高帧率下允许更大的图形复杂性。D3还允许通过事件对复杂的转换进行排序。你仍然可以使用CSS3转换;D3没有取代浏览器的工具箱,但以一种更容易使用的方式公开了它。
8 示例
请查阅:https://observablehq.com/@d3/gallery
想了解更多吗?请关注后续教程。