d3.js入门教程之数据绑定详解

作者:doraeimo 时间:2024-04-22 12:48:54 

前言

d3.js 是一款上手容易的js类库,专门用于绘制svg图形图表,其关键理念为data-join 意即数据绑定.搞清这个概念非常重要,它将以简洁优雅的形式体现数据驱动编程.

以下是Thinking with Joins的拙译 ,原作者Mike Bostock

假设你要用D3画一副散点图,因此需要生成一些 SVG circle 元素来直观地展现数据. 你会惊讶地发现D3没有提供原生的产生多个DOM元素的接口,

是的,只有一个 append 方法,用于产生单个DOM元素:


svg.append("circle")
.attr("cx", d.x)
.attr("cy", d.y)
.attr("r", 2.5);

但那只是单个圆,而你想要更多: 最好data*中每个元素对应一个圆. 在你用蛮力写循环把圆画出来之前,让我们看看D3中的一个例子:


svg.selectAll("circle")
.data(data)
.enter().append("circle")
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
.attr("r", 2.5);

*此处 data是一个 JSON 数组,其每个元素 由 x 和 y属性构成, 例如: [{"x": 1.0, "y":1.1},{"x": 2.0, "y":2.5}, …]. 另,SVG circle元素用cx,cy表达圆心坐标,r表达半径长度.

这份代码符合你的需求,即每个元素产生一个圆 , 通过x和y属性表达圆心的坐标.

selectAll("circle")是什么意思,为什么要在产生所有圆之前去选中根本不存在的元素呢?

原来事情是这样的:告诉D3你的目标,而不要告诉它具体怎么做. 在这个例子中,D3知道我们的意图是,要让选中的"circle"元素来响应数据的变化, selectAll即描述了这个目标;而无需一步步指挥D3产生多个圆.这个概念即data-join.

data-join的背后执行了以下步骤:

  • selectAll("circle") 返回了一个空的选择

  • 空的选择通过 data()方法将数据和DOM元素绑定,并产生三个虚拟的子集: enter, update and exit. enter()方法包含了待添加的数据及相应的DOM元素的占位符;update()包含了已与数据绑定的现有元素.剩下待移除的部分被包含在 exit ()方法中

  • 一开始选择的结果是空的,因此所有数据都是待添加,将全部出现在enter的结果中.

  • 无需循环,通过.enter().append("circle")将待添加的元素一次性加入到SVG容器.

为什么要这么麻烦呢? 为什么不直接提供原生接口? data-join的优雅之处在于抽象和解耦.上述代码在enter()里只是专心处理新增的元素,而update and exit分别专注于处理更新和待删除部分.这意味着你不用把所有DOM元素删了重绘,因此得以轻松应对实时变化的数据,甚至支持一些交互(如拖动)与渐变的效果!

这里是一个处理三种状态(增改删)的例子:


var circle = svg.selectAll("circle")
.data(data);

circle.enter().append("circle")
.attr("r", 2.5);

circle
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });

circle.exit().remove();

如果我们重复运行代码,它会每次重新计算 data-join. 如果新的数据集比原来的少,多余元素会出现在 exit 中并被remove()删除.反之亦然,新增的数据出现在enter()中通过append()添加DOM元素.若新老数据集大小不变,则所有数据只是更新坐标.(译注:上文中介于enter和exit之间的代码,update()会被隐式调用)

以joins的方式思考同时让你的代码更直观: 处理这三种状态的代码无需条件(if)和循环(for)分支,只需简单描述让图形去响应数据的变化即可.如果给定的enter, update 或 exit 的选择结果为空,则会自动跳过相应的代码块,以降低性能开销.

Joins 支持在特定状态(增/删/改)下执行操作.例如,可以在enter而非update代码块中,指定静态的attributes(例如圆的半径,用 "r" attribute指定) . 仰赖于精确改动目标元素和最小化DOM变更,你已经极大地提升了浏览器渲染的表现! 类似地,你可以在特定状态下表现渐变等动画效果. 例如新增的圆可以从无到有渐变(半径从0到2.5):


circle.enter().append("circle")
.attr("r", 0)
.transition()
.attr("r", 2.5);

待删除的圆也可以逐渐收缩直至消失:


circle.exit().transition()
.attr("r", 0)
.remove();

相信现在你已经学会用joins的方式思考了!

来源:http://blog.csdn.net/doraeimo/article/details/8707773

标签:d3.js,动态绑定
0
投稿

猜你喜欢

  • python实现字符串完美拆分split()的方法

    2023-08-25 13:50:36
  • mysql慢查询使用详解

    2024-01-25 05:07:18
  • python基于TCP实现的文件下载器功能案例

    2021-12-30 05:14:26
  • W3C优质网页小贴士(四)

    2008-04-17 13:34:00
  • PyCharm 光标变成黑块的解决方式

    2023-11-12 11:02:48
  • MySQL基于DOS命令行登录操作实例(图文说明) <font color=red>原创</font>

    2024-01-16 13:54:21
  • php的PDO事务处理机制实例分析

    2024-05-11 09:45:30
  • CentOS 7下部署php7.1和开启MySQL扩展的方法教程

    2023-11-19 11:58:09
  • 通过pycharm使用git的步骤(图文详解)

    2023-07-24 14:43:21
  • 浅谈MySQL数据查询太多会OOM吗

    2024-01-19 19:04:20
  • Python 列表(List)操作方法详解

    2023-06-15 10:10:04
  • SQL语句(T-SQL汇总) 用T-SQL画出这些图形

    2024-01-13 15:24:35
  • IE7的web标准之道 Ⅱ

    2008-08-13 12:50:00
  • ASP-server.URLEncode反函数:urldecode

    2008-10-23 16:05:00
  • Go语言判断指定文件是否存在的方法

    2024-05-21 10:21:38
  • Django利用AJAX技术实现博文实时搜索

    2023-01-02 01:57:50
  • python-yml文件读写与xml文件读写

    2022-06-16 06:43:50
  • MySQL学习笔记之数据定义表约束,分页方法总结

    2024-01-13 13:46:38
  • 无阻塞加载脚本分析[全]

    2024-04-17 10:25:35
  • Python使用xpath实现图片爬取

    2023-07-10 16:45:42
  • asp之家 网络编程 m.aspxhome.com