d3.js:数据可视化利器之 selection:选择集

jopen 9年前
原文  http://www.ituring.com.cn/article/202105

选择集/selection

选择集/selection是d3中的核心对象,用来封装一组从当前HTML文档中选中的元素:

d3.js:数据可视化利器之 selection:选择集

d3提供了两个方法用来创建selection对象:

  • select(selector) : 只使用第一个匹配的元素创建选择集。
  • selectAll(selector) : 使用全部匹配的元素创建选择集。

select:选中单个元素

select()方法用来创建最多只包含一个DOM元素的选择集。如果当前文档中 没有匹配的元素,则建立一个空选择集;如果当前文档中有多个匹配的元素, 也只用第一个匹配元素建立选择集。

有两种方法调用select():

  • 使用CSS3选择符指定匹配条件

最常用的调用方法是传入一个CSS3选择符字符串:

d3.select(selector)

  • 将DOM对象转化为选择集对象

有时我们需要将一个DOM对象转化为一个选择集对象,这时可以直接向select() 方法传入这个DOM对象:

d3.select(node) 一种常见的应用场景是在事件回调函数中,将this转化成选择集对象: d3.select(this),因为这时this指向触发事件的DOM元素。

selectAll:选中多个元素

selectAll()方法用来创建可包含多个DOM元素的选择集。如果当前文档中 没有匹配的元素,则建立一个空选择集;如果当前文档中有多个匹配的元素, 则使用所有匹配元素建立选择集。

和select()方法一样,也有两种方式调用selectAll()方法:

  • 使用CSS3选择符指定匹配条件

最常用的调用方法是传入一个CSS3选择符字符串:

d3.selectAll(selector)

  • 将一组DOM对象转化为选择集对象

如果已经获得了一组DOM对象,可以直接将其转化为选择集对象:

d3.selectAll(nodes) 比如,在事件回调函数中,使用d3.select(this.childNodes)创建选择集。

为什么需要选择集?

d3定义选择集对象的一个目的是封装对DOM的操作。选择集提供了众多的方法(d3称之为 操作符/operator)来进行DOM操作,比如设置属性、样式、文本内容以及监听 DOM事件等。从这个角度看,d3的选择集对象类似于jQuery中的$对象,如果你 从jQuery过来,应该容易理解这一点:

  1. var s = d3.selectAll("div"); //选中所有div元素创建选择集对象:s
  2. s.text("demo"); //使用选择集对象的text()方法设置这些div元素的文本内容
  3. var $s = $("div"); //选中所有div元素创建jQuery对象:$s
  4. $s.text("demo"); //使用jQuery对象的text()方法设置这些div元素的文本内容

有趣的是,d3的选择集对象和jQuery对象一样,也具有链式调用的能力。绝大多数的选择 集操作符返回的结果还是一个选择集(可能和最初的选择集内容不一样),这使得调用可以持续下去, 像一条流水线:

d3.js:数据可视化利器之 selection:选择集

容易理解,选择集是d3中文档处理流水线的开端,选择集的操作符就是流水线中的各个 处理环节,当选择集流过流水线,原始文档的修改就自然而然地发生了。

插入数据驱动环节

d3定义选择集对象的更深层次的目的是封装数据驱动能力。通过data() 操作符,d3使数据化可视化工作者能够以一种声明式的方式指定处理流水线,从而 简化从数据到文档的处理过程:

d3.js:数据可视化利器之 selection:选择集

和style()这样的操作符不同,data()操作符能够改变选择集的内容。 当选择集流过style()环节后,选择集的内容并没有变化,变化的是选择集中 各个DOM对象的属性。然而,当一个选择集流过data()环节后,将获得一个不同的选择集: 所包含的DOM对象发生了变化。

each: 定制处理行为

each()方法允许我们定制对选择集中DOM元素的处理行为:

selection.each(func) 参数func是调用者定义的函数,在d3中被称为访问器/accessor。 d3将对选择集中的每一个DOM对象,依次调用该访问器函数。

在调用访问器函数时,d3会将this指向当前要处理的DOM对象, 并传入两个参数:

  • datum : 当前DOM对象对应的数据
  • index :当前DOM对象在集合中的序号

可以认为访问器是d3流水线中每个处理环节用户逻辑的封装接口,d3通过这个接口, 实现了流水线框架和用户处理逻辑的解耦:

d3.js:数据可视化利器之 selection:选择集

几乎所有的操作符在内部实现中都使用了each(),每当d3提供的操作符 不能满足你的需求时,都不妨试一试each()。

示例演示: http://www.hubwiz.com/course/54fd40cfe564e50d50dcf284/