简介: 出于个人学习目的, 计划将 D3 的学习资料逐步翻译为系列文章, 鉴于本人水平有限, 如有不到或错误之处, 欢迎大家指正, 谢谢!
概述
D3.js 是用于操作和管理基于数据的文档的 JavaScript 函数库. D3 帮助你使用 html,SVG 和 CSS 技术把您的数据活灵活现的展示出来. D3 注重于 web 规范, 从而让您使用现代浏览器的全部功能而不用使用商业框架, 将强大的数据呈现组件与基于数据驱动的模式组合进 DOM 操作之中.
您可以从这里下载最新版本(5.4.0):
https://github.com/d3/d3/releases/download/v5.4.0/d3.zip
如果您想直接使用最新版本, 复制如下的代码段:
<script src="https://d3js.org/d3.v5.min.js"></script>
本项目所有完整的源代码和测试文件可以从 GitHub https://github.com/d3/d3 下载.
简介
D3 可以让您将任意数据绑定至文档对象模型(DOM), 然后基于数据驱动原理操作文档的生成. 比如, 您可以从数组自动生成 HTML 表格, 或者, 使用同一个数据生成动态的, 具有平滑转换和交互功能的 SVG 柱状图.
D3 不是一个努力提供一切可能功能的整体性框架, 相反, D3 解决的是问题中的难题: 高效的基于数据的文档操作. 这样做, 虽然偏离了商业软件的简洁性, 却提供了超强的灵活性, 透露出了对于 HTML,SVG 和 CSS 等网页标准的完整操作能力. 在极小的运算下, D3 运行如飞, 支持海量数据库和交互与动画的动态呈现. D3 的实现风格维持了大量官方和社区开发的模块的代码可重用性.
选择器
使用 W3C COM API 接口修改文档结构是一个痛苦的事情: 函数名过长, 交互过程需要手工迭代及临时状态的管理. 比如, 要修改段落元素的字体颜色:
- var paragraphs = document.getElementsByTagName("p");
- for (var i = 0; i < paragraphs.length; i++) {
- var paragraph = paragraphs.item(i);
- paragraph.style.setProperty("color", "white", null);
- }
D3 发明了选择器, 基于声明的方式实现对任意节点的操作. 比如, 你可以用如下的方式重写上面的代码:
d3.selectAll("p").style("color", "white");
而且, 您可以根据需要继续操作独立的节点:
d3.select("body").style("background-color", "black");
选择器语法基于 W3C 选择器 API https://www.w3.org/TR/selectors-api/ , 该语法已被现代浏览器支持. 在以上代码之中, 我们通过标签名称选择节点("p" 和 "body"). 元素还可以使用一系列的标记实现选择, 包括包含关系, 属性值, class 及 id.
D3 提供大量的方法来转变节点: 设置属性或样式, 注册事件处理器, 节点的添加删除和排序, 修改 HTML 或文字内容. 目前这些功能已经足够满足绝大多数需求. 您也可以直接访问其下的 DOM 内容, 每个 D3 选择结果就是节点的数组.
动态属性
如果有读者熟悉类似 jQuery 等其他 DOM 框架的话, 应该很快发现和 D3 的相似性. 然而在 D3 之中, 样式及其他属性不仅仅可以通过常量设置, 还可以通过参数函数来设置. 这一点虽然看起来很简单, 却非常强大. 我们以 d3.geoPath https://github.com/d3/d3-geo/blob/master/README.md#geoPath 函数为例, 可以将地理坐标系 https://tools.ietf.org/html/rfc7946 转化为 SVG 路径数据 https://www.w3.org/TR/SVG/paths.html#PathData .D3 提供大量内置的可重用函数及函数库, 比如图形元素 https://github.com/d3/d3-shape , 可以用于面积, 线段和饼状图的绘制.
举例如下, 用随机色彩渲染段落:
- 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";
- });
计算属性经常与绑定的数据有关, 我们通过数组来指定数据, 每个数值则被传送到选择器的参数函数的第一个参数(d). 按照默认根据索引序号的分配方式, 第一个数据传送给了选择结果的第一个节点, 第二个数据则传送给了第二个节点等等. 比如, 如果您将数组绑定到了段落元素, 就可以用这些数据来动态分配字体大小:
- d3.selectAll("p")
- .data([4, 8, 15, 16, 23, 42])
- .style("font-size", function(d) { return d + "px"; });
一旦数据被绑定到了文档, 你可以忽略 data 操作器, D3 将自动按照原有设置分配其中的数据, 这样就可以方便的重新设置数据而不用重新绑定.
enter 与 exit 选择器
有了 D3 的 enter 和 exit 选择器, 你可以使用新进数据创建节点, 同时抛弃不需要的节点.
在将数据绑定到选择结果时, 每个数值都被分配到了对应的选择元素. 如果选择元素的数量比数据数量要少, 多余的数据则进入了 enter 选择器, 比如:
- d3.select("body")
- .selectAll("p")
- .data([4, 8, 15, 16, 23, 42])
- .enter().append("p")
- .text(function(d) { return "I'm number "+ d +"!"; });
在以上代码中, 节点被按照 data 操作器中的数据更新. 如果您忘记使用 enter 和 exit 选择器, 将自动采用数据之中元素参数相对应并存在的结果进行选择. 我们将选择分类为三部分: 要更新的节点, 要增加的节点, 要移除的节点.
- // 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();
通过以上三种后续代码的操作, 您可以精确的制定何种结果采用什么样的操作, 提高了性能同时提供了数据转换的更好控制. 比如在柱状图中, 您可以使用旧的比例初始化增加的节点, 然后对三类节点设定单独的比例.
D3 让您可以基于数据转变文档, 包括要创建和要被销毁的元素. D3 让您可以根据用户交互, 时间动画甚至第三方插件的异步消息来修改文档. 您也可以使用组合的方案, 比如一开始在服务器上渲染了文档, 然后在客户端用 D3 来更新文档.
变形, 不是呈现
D3 不像 Processing https://processing.org/ 或 Protovis https://mbostock.github.io/protovis/ 那样引入新的视觉效果, D3 的一切图形标记语言都源于 Web 标准: HTML,SVG 和 CSS. 比如, 您可以用 D3 创建 SVG 元素然后用其他样式表渲染, 也可以组合使用滤镜, 虚线和剪切效果. 乃至于如果未来浏览器开发者提供了新的功能, 您可以理解进行应用而无需其他工具包. 如果您未来决定采用其他工具来替代 D3, 您也可以带着学到的知识一同前进.
最好的是, D3 可以轻松的用浏览器的内置元素浏览器调试, 您所操作的节点正是浏览器所管理的内容.
过渡
D3 的变形可以轻松的通过对样式与属性动态插值扩展成动态过渡. 您可以轻松的通过函数 (比如 "elastic","cubic-in-out" 和 "linear") 对插值进行控制. D3 的插值器支持数值 (比如数据和嵌入在字符串中的属性, 字体大小, 路径数据等) 与组合数据. 您甚至可以将 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 不会修改浏览器的工具包, 而是让以一种更容易的方式被使用.
想学更多吗? 您可以阅读这些教程 https://github.com/d3/d3/wiki/Tutorials .
个人笔记
一直以来, 本人都在寻找更合适自己的基于浏览器的图形绘制框架. 目前市面上有很多高上大的准商业范畴的开源或不开源工具库, 但是没有一个比 D3 更灵活和更容易实现自己的复杂想法.
D3 很多时候被人们错认为与 jQuery 是同台竞争的产品, 实际上这是一个错误认识. 自从诞生之初至今, D3 虽然与 jQuery 一样致力于 DOM 元素的管理和操作, 但 D3 的开发目标始终在数据呈现上而不是网页开发.
D3 的功能目标, 是让每个人都可以封装一个可以实现自己数据呈现想法的 Javascript 工具函数, 来让 HTML 中的任意节点, 占位符瞬间转变为图标或动态呈现内容.
在与 D3 同台竞争的诸多数据呈现工具之中, 大量有着商业插件风格的简单易用, 同时也被高度封装而让人很难参与和理解其中的实现过程. D3 诞生于学术, 发扬于学院派精神, 让自己渺小的停留在工具库的范畴, 同时给应用者发挥足够想象空间的余地.
当然, 伴随学院派风格, D3 这么多年来市场占有率低下, 也离不开它本身的设计哲学. 复杂的模块化和文档的分散, 体系化教程的匮乏让许多感兴趣的人最终在学习曲线和时间效率下离开, 望而却步. 能够有一个好的文档, 教程体系, 是让一套强大工具被人们所理解并大量广泛应用的前提基础.
在以后的日子里, 本人将逐渐根据个人理解翻译 D3 的官方文章, 教程. 一方面, 为本人学习 D3 的过程中留下想法和笔记, 另一方面, 希望这个努力能让更多对数据呈现感兴趣的学生, 程序员和设计师能够有一个基于中文的轻松氛围, 来学习, 理解, 使用和发挥 D3 这套国外的高效插件, 努力让大家都能受益.
来源: http://www.jianshu.com/p/d74cd5e03e21