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


Posted in Javascript onApril 28, 2017

前言

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的方式思考了!

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
javascript 兼容鼠标滚轮事件
Apr 07 Javascript
js监听鼠标事件控制textarea输入字符串的个数
Sep 29 Javascript
arguments对象验证函数的参数是否合法
Jun 26 Javascript
javascript实现动态标签云
Oct 16 Javascript
jQuery实现简单的网页换肤效果示例
Sep 18 Javascript
Bootstrap CSS组件之按钮组(btn-group)
Dec 17 Javascript
深入研究React中setState源码
Nov 17 Javascript
详解JS数值Number类型
Feb 07 Javascript
Vue.js 中的 v-model 指令及绑定表单元素的方法
Dec 03 Javascript
JS实现集合的交集、补集、差集、去重运算示例【ES5与ES6写法】
Feb 18 Javascript
layui实现下拉复选功能的例子(包括数据的回显与上传)
Sep 24 Javascript
JavaScript简单编程实例学习
Feb 14 Javascript
jQuery tip提示插件(实例分享)
Apr 28 #jQuery
JS实现动态添加DOM节点和事件的方法示例
Apr 28 #Javascript
jQuery自定义元素右键点击事件(实现案例)
Apr 28 #jQuery
详解angularJs模块ui-router之状态嵌套和视图嵌套
Apr 28 #Javascript
vue基于Vue2.0和高德地图的地图组件实例
Apr 28 #Javascript
d3.js实现立体柱图的方法详解
Apr 28 #Javascript
JS基于正则表达式的替换操作(replace)用法示例
Apr 28 #Javascript
You might like
ThinkPHP调试模式与日志记录概述
2014/08/22 PHP
PHP带节点操作的无限分类实现方法详解
2016/11/09 PHP
php文件上传原理与实现方法详解
2019/12/20 PHP
JavaScript面向对象之Prototypes和继承
2012/07/12 Javascript
javascript实现获取cookie过期时间的变通方法
2014/08/14 Javascript
用js读、写、删除Cookie代码续篇
2014/12/03 Javascript
jQuery插件jcrop+Fileapi完美实现图片上传+裁剪+预览的代码分享
2015/04/22 Javascript
js+HTML5基于过滤器从摄像头中捕获视频的方法
2015/06/16 Javascript
JS判断页面是否出现滚动条的方法
2015/07/17 Javascript
jquery实现的3D旋转木马特效代码分享
2015/08/25 Javascript
js获取表格的行数和列数的方法
2015/10/23 Javascript
JavaScript中三个等号和两个等号的区别(== 和 ===)浅析
2016/09/22 Javascript
Angular 输入框实现自定义验证功能
2017/02/19 Javascript
vue+webpack实现异步组件加载的方法
2018/02/03 Javascript
ES6中let 和 const 的新特性
2018/09/03 Javascript
详解webpack4之splitchunksPlugin代码包分拆
2018/12/04 Javascript
微信小程序 自定义复选框实现代码实例
2019/09/04 Javascript
解决vue项目F5刷新mounted里的函数不执行问题
2019/11/05 Javascript
微信小程序手动添加收货地址省市区联动
2020/05/18 Javascript
使用Turtle画正螺旋线的方法
2017/09/22 Python
Numpy数组的保存与读取方法
2018/04/04 Python
解决Spyder中图片显示太小的问题
2018/04/27 Python
python得到单词模式的示例
2018/10/15 Python
Django中在xadmin中集成DjangoUeditor过程详解
2019/07/24 Python
python实现比对美团接口返回数据和本地mongo数据是否一致示例
2019/08/09 Python
用python实现名片管理系统
2020/06/18 Python
德国汉莎航空中国官网: Lufthansa中国
2017/03/30 全球购物
全球第二大家装零售商:Lowe’s
2018/01/13 全球购物
FitFlop美国官网:英国符合人体工学的鞋类品牌
2018/10/05 全球购物
俄语专业毕业生推荐信
2013/10/28 职场文书
美术第二课堂活动总结
2014/07/08 职场文书
建筑安全责任书范本
2014/07/24 职场文书
评奖评优个人先进事迹材料
2015/11/04 职场文书
七年级作文之《我和我的祖国》观后感作文
2019/10/18 职场文书
Python使用sql语句对mysql数据库多条件模糊查询的思路详解
2021/04/12 Python
SQL解决未能删除约束问题drop constraint
2022/05/30 SQL Server