这里转载一个非常经典的关于D3数据绑定的帖子,由D3作者自己写的,非常棒,以至于我忍不住全文copy到此。

原文地址

Thinking with Joins

Say you’re making a basic scatterplot using D3, and you need to create some SVG circle elements to visualize your data. You may be surprised to discover that D3 has no primitive for creating multiple DOM elements. Wait, WAT?

Sure, there’s the append method, which you can use to create a single element.

Here svg refers to a single-element selection containing an<svg> element created previously (or selected from the current page, say).

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

But that’s just a single circle, and you want many circles: one for each data point. Before you bust out a for loop and brute-force it, consider this mystifying sequence from one of D3’s examples.

Here data is an array of JSON objects with x and y properties, such as: [{"x": 1.0, "y":1.1}, {"x": 2.0, "y":2.5}, …].

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);

This code does exactly what you need: it creates a circle element for each data point, using the x andy data properties for positioning. But what’s with the selectAll("circle")? Why do you have to select elements that you know don’t exist in order to create new ones? WAT.

Here’s the deal. Instead of telling D3 how to do something, tell D3 what you want. You want the circle elements to correspond to data. You want one circle per datum. Instead of instructing D3 to create circles, then, tell D3 that the selection "circle" should correspond to data. This concept is called the data join:

Data points joined to existing elements produce the update (inner) selection. Leftover unbound data produce the enter selection (left), which represents missing elements. Likewise, any remaining unbound elements produce the exit selection (right), which represents elements to be removed.

Now we can unravel the mysterious enter-append sequence through the data join:

  1. First, svg.selectAll("circle") returns a new empty selection, since the SVG container was empty. The parent node of this selection is the SVG container.

  2. This selection is then joined to an array of data, resulting in three new selections that represent the three possible states: enterupdate, and exit. Since the selection was empty, the update and exit selections are empty, while the enter selection contains a placeholder for each new datum.

  3. The update selection is returned by selection.data, while the enter and exit selections hang off the update selection; selection.enter thus returns the enter selection.

  4. The missing elements are added to the SVG container by calling selection.append on the enter selection. This appends a new circle for each data point to the SVG container.

Thinking with joins means declaring a relationship between a selection (such as "circle") and data, and then implementing this relationship through the three enterupdate and exit states.

But why all the trouble? Why not just a primitive to create multiple elements? The beauty of the data join is that it generalizes. While the above code only handles the enter selection, which is sufficient for static visualizations, you can extend it to support dynamic visualizations with only minor modifications for update and exit. And that means you can visualize realtime data, allow interactive exploration, and transition smoothly between datasets!

Here’s an example of handling all three states:

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

To control how data is assign­ed to elements, you can pro­vide akey function.

Whenever this code is run, it recomputes the data join and maintains the desired correspondence between elements and data. If the new dataset is smaller than the old one, the surplus elements end up in the exit selection and get removed. If the new dataset is larger, the surplus data ends up in theenter selection and new nodes are added. If the new dataset is exactly the same size, then all the elements are simply updated with new positions, and no elements are added or removed.

Thinking with joins means your code is more declarative: you handle these three states without any branching (if) or iteration (for). Instead you describe how elements should correspond to data. If a given enterupdate or exit selection happens to be empty, the corresponding code is a no-op.

Joins also let you target operations to specific states, if needed. For example, you can set constant attributes (such as the circle’s radius, defined by the "r" attribute) on enter rather than update. By reselecting elements and minimizing DOM changes, you vastly improve rendering performance! Similarly, you can target animated transitions to specific states. For example, for entering circles to expand-in:

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

Likewise, to shrink-out:

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

Now you’re thinking with joins!

D3数据绑定的更多相关文章

  1. d3 数据绑定

    绑定过程 选择元素,绑定数据,追加元素 <!DOCTYPE html> <html> <head> <title>testD3-.html</ti ...

  2. d3基础入门一-选集、数据绑定等核心概念

    引入D3 D3下载,本文下载时的版本为6.5.0 mkdir d3.6.5.0 unzip --help unzip d3.zip -d d3.6.5.0/ ls d3.6.5.0/ API.md C ...

  3. d3可视化实战02:理解d3数据驱动的真正含义

    前文中已经提到,SVG从诞生之初起就可以非常方便地使用javascript脚本语言来进行其DOM对象的控制.当然,控制的方法有很多,有直接控制SVG对象的方法,例如使用原生js:有帮你封装一下图形接口 ...

  4. d3.js入门之DOM操作

    上篇成功在vue项目中把d3跑起来了,接下来对d3的基本操作做个汇总: 一.d3元素选择器 d3.select(".skill"):选择第一个类名为skill的元素并返回这个元素对 ...

  5. node+ts的心得与坑

    首先先明确,用node+ts的目的,为什么不ng+ts.这一点后面还会反复提醒自己 node毕竟不是ng. 用node的理由: 处理js,在后端操纵dom,读写类html格式的东西,比直接用py的后端 ...

  6. D3.js(v3)+react框架 基础部分之数据绑定及其工作过程与绑定顺序

    数据绑定: 将数据绑定到Dom上,是D3最大的特色.d3.select和d3.selectAll返回的元素的选择集.选择集上是没有数据的. 数据绑定就是使被选择元素里“含有”数据. 相关函数有两个: ...

  7. 一个初学者的指南,使用D3做数据绑定

    一个初学者的指南,使用D3做数据绑定 D3.js 是个强大的数据可视化库,可以做出惊艳的图表.比如:气泡图,线图和条形图--只需要很少行的代码 随着初学者对JavaScript的理解,可以将数组或者对 ...

  8. D3.js学习笔记(一)——DOM上的数据绑定

    开始学习D3.js,网上没有找到很满意的中文教程,但是发现了一个很好的英文教程,讲解的非常详细.从一个初始简单的HTML网页开始,逐步加入D3.js的应用,几乎是逐句讲解.学习的时候,就顺便翻译成中文 ...

  9. d3 data()数据绑定中的key函数

    官网https://github.com/d3/d3-selection/blob/master/README.md#selection_data var data = [ {name: " ...

随机推荐

  1. Jquery 插件\Js 插件收集

    1.linq.js 使得js 的数组像c#的linq操作一下样 http://linqjs.codeplex.com/ 2.分页插件 https://github.com/mricle/Mricode ...

  2. vtkTubeFilter实例

    filter that generates tubes around lines vtkTubeFilter is a filter that generates a tube around each ...

  3. yield生成器及字符串的格式化

    一.生成器 def ran(): print('Hello world') yield 'F1' print('Hey there!') yield 'F2' print('goodbye') yie ...

  4. python基础知识(三)

    摘要:主要涉及新数据类型set集合.三元运算.深浅拷贝.函数基础.全局变量与局部变量 一.set --> 无序,不允许重复的集合 不允许重复的列表,   1,创建    s = set() 接收 ...

  5. SVN搭建简单教程

    一.引言 笔者曾经试图在网上搜索一篇关于SVN源代码服务器搭建方面的中文技术文章,可惜,所找到的,要么是不完整,要么就是对笔者没什么帮助的文章,TortoiseSvn的帮助文档固然强大,但因为是英文, ...

  6. applicationContext.xml的基本配置文件

    <?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.spr ...

  7. 安卓ApiDemos最简单的使用方法

    http://download.csdn.net/detail/ffwmxr/7401067#comment 正确使用方法:开新工程, 名字API Demos,将下载文件里的 src,res, And ...

  8. mac gem install nokogiri error

    Gem::Ext::BuildError: ERROR: Failed to build gem native extension. /Users/angela/.rbenv/versions/1.9 ...

  9. [BZOJ1552][Cerc2007]robotic sort

    [BZOJ1552][Cerc2007]robotic sort 试题描述 输入 输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000.第二行为N个用空格隔开的正整数 ...

  10. 基础的jdbc连接数据库操作

    首先我们知道在数据库中,我们可以直接写sql或者直接通过数据库工具操作数据,但是在java程序中我们是不能直接操作数据库数据的,所以这就引入了jdbc操作. 百度百科:JDBC(Java Data B ...