D3.js version4教程(2)
选择集
选择集是html文档中选择的元素的集合.操作文档的手段.
数据驱动文档都是基于对文档选择集的操作.
选择元素
选择元素的函数主要是这两个:
- select:返回匹配选择器的第一个元素
- selectAll:返回匹配选择器的所有元素.
选择器的基础是selection对象,对于D3层次的选择器,即d3.select()
和d3.selectAll()
,会从整个文档进行搜索. 而子选择器,只是会从当前子选择集中开始搜索.
选择的API
d3.selection()
Selects根元素,document.documentElement
. 这个方法可以被用来测试一个选择集是否是d3.selection的实例(instanceof d3.selection
) 或者扩展选择集的属性.selection是选择集的对象,select()方法返回的对象都是这个类型.selection.filter(filter)
过滤选择集,返回一个新的选择集。会对选择集中的每个元素进行调用filter方法(或匹配CSS字符串),filter返回true时,才保留这个元素。filter方法传递当前元素绑定的数据d,索引i以及当前的分组nodes,this指向当前的元素。selection.merge(other)
将other对应的选择集合并到selection上,返回的选择集与selection具有相同个数的分组和父节点d3.matcher(selector)
根据指定的selector返回一个函数,这个函数可以接受一个元素,并判断这个元素是否满足selector,如果满足则返回true否则返回falsed3.selector(selector)
根据指定的selector, 返回一个可以匹配第一个满足selector元素的方法
修改元素的API
首先将文档中的选择集选中,选中后,可以对选择集的对象进行操作,以下就是操作的一些api
- election.attr(name[, value])
如果指定了value参数则这个方法就是设置,如果只有name参数则是获取,下同。
设置或获取元素的name属性。
value可以是一个变量,也可以是一个方法,如果是方法,则会执行这个方法,并传递当前元素绑定的数据 (d), 索引(i), 以及当前分组(nodes), this指向的是当前的元素,将方法的返回值作为name对应的值。
name可能是一个带前缀的属性,比如 xlink:href来指定href属性的命名空间
selection.classed(names[, value])
设置或获取指定的类名状态,如果指定了value则根据value值启用或关闭类。如果没有指定value则相当于查询指定类的状态。name可以同时指定多个,使用空格隔开selection.style(name[, value[, priority]])
如果指定了value,则设置对应的样式为value。value可以为变量,也可以为一个函数,函数会传递当前元素绑定的数据d,索引i以及当前的分组groups。在函数内部this指向当前的元素,函数的返回值作为样式的值。可选的priority可以设置为默认的null或字符串important (没有感叹号).
如果没有指定value则返回当前选择集第一个非null元素经过计算后的样式值,要注意计算后的值 可能与设置值不同,尤其是使用了速写方法(比如font样式代替标准的font-size,font-face样式,等等).selection.property(name[, value])
一些HTML元素有些属性不能使用attribute或styles来查询或设置。比如form表单的text元素值以及checkbox的checked值。这时候就需要使用selection.property(name[,value])来设置或读取。selection.text([value])
设置或获取text content内容。可以使用这个方法清空元素内容。selection.html([value])
设置或获取inner HTML内容。可以使用这个方法清空元素内容selection.append(type)
如果type是一个字符串,则在选择集中的每个元素的子元素末尾追加一个元素。如果selection是一个enter selection,则将元素追加到元素末尾,作为选择集中元素的下一个兄弟节点。enter操作可以将数据与DOM元素的顺序对应,当然也可以使用效率更慢一点的selection.order操作进行手动排序。
此外,type还可以是一个方法,则会传递d,i,nodes为参数,并在函数内部返回一个元素。这个元素类型可以根据实际需要选择。换句话说,就是如果type是一个方法的话,添加的元素就不一定是同一种类型.selection.insert(type, before)
如果type是一个字符串,则在指定的元素前插入一个新元素。如果type为一个函数,则会传递d,i,nodes为参数,并将返回的元素插入到选择集中。type和before都可以使用函数代替- selection.remove()
从文档中将选择集移除,并返回移除的选择集。 - selection.sort(compare)
返回一个新的经过排序的选择集。参数为一个比较方法。 selection.order()
重新插入元素到文档中,以使每个组的文档顺序与选择顺序匹配。如果数据顺序已经排好等价于调用selection.sort但是更快.selection.raise()
重新将元素插入到对应父元素,作为父元素的最后一个子元素selection.lower()
重新将元素插入到对应父元素,作为父元素的第一个子元素d3.creator(name)
根据指定的元素名,返回一个可以创建对应子元素的方法
绑定数据
选择好元素后,需要在选择集上绑定数据,这样才能实现数据驱动文档.
根据数据的多少和文档元素的多少可以分成三个部分:
1. update():该选择集给出了文档元素和数据绑定的部分
2. enter():该选择集给出了数据元素比文档元素多的那个部分
3. exit():该选择集给出了文档元素比数据部分多的那个部分
具体场景:对于一个图表,数据是一个数组a[1,2,3,4,5];想把这些数都显示在html中的div上.当通过selectAll(‘div’),选择的时候,返回的选择集中有10个div.通过data(a)绑定的时候,就分别产生了上面三个部分.update部分是a中元素对应div中的5个那部分,enter部分是在此情况下是空,因为没有剩余的数据没有绑定.exit()部分是剩余的5个元素没有数据的那部分.
主要的api如下:(剩余的API可查(官方文档[https://github.com/d3]).)
selection.data([data[, key]])
将数组类型的data与选择集中的元素绑定,返回一个update集:数据与元素绑定。因为数据个数未必与元素个数一致,所以又有enter 和 exit操作。data元素可以是任意类型,比如数值类型或对象类型。也可以是一个返回一个数组的函数. 元素会以data这个属性存储绑定的数据。这样就可以使数据作为元素的一个属性存在有利用根据数据反复对元素操作而不需要每次操作都绑定一次.selection.enter()
返回一个enter集,准确来说是一个DOM元素占位符,此时没有任何元素,需要使用append方法添加元素,enter集通常用来创建缺失的元素selection.exit()
返回exit集:现有的元素没有被数据绑定时将没有数据的这些元素返回。selection.datum([value])
获取选中的元素的数据或者为选中的元素绑定数据。与selection.data不同, 这个方法不去计算数据元素和DOM元素的结合,也就是不影响索引或enter集和exit集。
选择集的事件处理
selection允许分发和监听事件.
事件处理主要是一些交互过程,比如用户移动鼠标到图表上,用户点击的操作,会触发事件,或者更新一些数据.
这个过程是在选择集上进行处理的.
常用事件处理API
selection.on(typenames[, listener[, capture]])
添加或移除选择集中的每个元素上事件类型为typenames的事件。typenames是一个表示事件类型的字符串,比如click, mouseover, 或 submit; 任何浏览器支持的DOM event type 都可以使用. type和name之间可以使用(.)隔开,以为同一种事件类型添加不同的事件监听器;比如click.foo 和 click.bar. 同时指定多个typenames时可以使用空格隔开,比如 input change 或 click.foo click.bar.
当一个指定的事件被分发到一个被选中的元素节点上时,对应的listener将会被调用并传递绑定的数据(d),索引(i), 当前的分组(nodes), 回调中的this指向的是当前的DOM元素. 通过 d3.event访问当前的事件对象.
如果之前已经为typenames注册了事件监听器,则会覆盖。如果listener为null则会移除typenames对应的事件监听器。此时要注意事件类型的匹配,比如向.foo传递null则所有name为foo的事件监听器都被移除,类似于CSS类的选择模式。
可选的capture标识相当于W3C 的 useCapture flag:当启用事件捕获后,指定类型的事件将被,默认为false。
如果没有指定listener,则返回typenames对应的事件监听器,如果指定了多个typenames则只返回第一个。selection.dispatch(type[, parameters])
为选择集中的每个元素分发一个类型为type的custom event,也就是等于在选择集上触发了type事件, parameters对象可以指定事件的一些属性:
bubbles
- 如果为true则这个事件可以冒泡.
cancelable
- 如果为true则等于调用了event.preventDefault.
detail
- 可自定义一些数据传给回调.
如果parameters是一个方法,则会对选中的每个元素调用。并传递当前元素的的(d),(i)和(nodes), this指向DOM元素. 这个方法必须返回对象类型.d3.event
当前的event, 如果有的话. 这个属性再事件发生时被设置, 并在事件回调结束后被重置. 可以使用这个来访问标准的事件对象属性,比如event.timeStamp 以及方法比如 event.preventDefault. 也可以使用 event.pageX 和 event.pageY, 这个是很方便的因为不需要使用d3.mouse, d3.touch 或 d3.touches对原生事件对象进行坐标转换 .d3.customEvent(event, listener[, that[, arguments]])
调用指定的listener,使用指定的that this上下文并传递指定的参数arguments. 在调用期间d3.event会被设置为指定的event对象; 在调用结束后d3.event被重新设置为之前的值.d3.mouse(container)
返回当前current event相对于container的x和y坐标。container可以为HTML,SVG元素,比如G element 或SVG element. 返回值是一个包含两个元素的数组[x, y].
参数是一个node对象,而不是selectiond3.touch(container[, touches], identifier)
返回当前标志符为identifier的current event相对于container的x和y坐标。container可以为HTML,SVG元素,比如G element 或SVG element. 返回值是一个包含两个元素的数组[x, y].
如果当前指定的identifier没有触摸事件,则返回null。使用标示符可以忽略触摸拖动事件。如果没有指定touches则默认为当前事件的changedTouches 属性.d3.touches(container[, touches])
返回当前触摸current event相对于container的x和y坐标。container可以为HTML,SVG元素,比如G element 或SVG element。由于可能存在多个触摸点,因此这个方法返回一个二维数组表示所有的触摸点,返回的形式为 [[x1, y1], [x2, y2], …]. 如果没有指定 touches 则默认为当前事件的touches 属性.