这部分承接上一篇,介绍d3-selection模块中的修改元素节点部分和命名空间。看源码戳
selection模块结构
- 选择元素
- 修改元素(本章的内容)
- 加入数据
- 处理事件
- 控制流
- 局部变量
- 命名空间(本章的内容)
选择元素
选择元素后,设置文档的不同属性,例如设置a的name和color:
evs.select("a")
.attr("name", "fred")
.style("color", "red");
可以直接去d3js.org官网在控制台中做实验。
selection.attr(name[, value]) :
如果指定了value,则将为name的attribute设置为value,并返回选择器,value为常量,则对应属性都设置为该值,如果为函数,会传入数据(d)、索引(i)、当前节点(node),使用返回值来设置属性,空值会删除对应属性。
如果未指定value,返回选择器中第一个非空元素的指定属性的值。
其中name可能会包含命名空间前缀,如xlink:href,参阅evs.spacenames,额外命名空间也可添加。
代码实现中,首先单个参数会直接返回对应属性,封装的getAttribute和getAttributeNS,传入两个参数时,value为null直接删除,封装removeAttribute,传入函数的情况又用到了闭包,在外部使用this.each(callback)传递。
function attrFunction(name, value) {
return function() {
var v = value.apply(this, arguments);
if (v == null) this.removeAttribute(name);
else this.setAttribute(name, v);
};
}
selection.classed(names[, value])
如果指定了value,在该选择器元素下可以将names添加或删除,修改classList属性吗,例如将类foo和bar添加到选择器。
selection.classed("foo bar", true);
如果value为true,所有选择器中元素会添加指定的类,否则不会添加。若value为函数,计算返回值判断是否添加,例如foo类随机数大于0.5时添加
selection.classed("foo", () => Math.random() > 0.5);
没指定value时,对第一个非空的节点进行判断,返回true或false。
代码实现中:防止不支持classList作者自定义了一个对象ClassList,以及对classList的添加删除包含操作,代码如下:
function ClassList(node) {
this._node = node;
this._names = classArray(node.getAttribute("class") || "");
}
ClassList.prototype = {
add: function(name) {
var i = this._names.indexOf(name);
if (i < 0) {
this._names.push(name);
this._node.setAttribute("class", this._names.join(" "));
}