D3选择v4(一、selection)中文
选择允许对文档对象模型(DOM)进行强大的数据驱动转换:设置属性,样式,属性,HTML或文本内容等。使用数据连接的进入和退出选择,您还可以添加或删除与数据对应的元素。
选择方法通常返回当前选择或新选择,允许通过方法链对给定选择上的多个操作进行简洁应用。例如,要设置当前文档中所有段落元素的类和颜色样式:
d3.selectAll("p") .attr("class", "graf") .style("color", "red");
这相当于:
var p = d3.selectAll("p");
p.attr("class", "graf");
p.style("color", "red");
按照惯例,返回当前选择的选择方法使用四个缩进空间,而返回新选择的方法仅使用两个。这有助于通过使它们脱离链条来揭示上下文的变化:
d3.select("body")
.append("svg")
.attr("width", 960)
.attr("height", 500)
.append("g")
.attr("transform", "translate(20,20)")
.append("rect")
.attr("width", 920)
.attr("height", 460);
选择是不可变的。影响选择哪些元素(或其顺序)的所有选择方法都返回新选择而不是修改当前选择。但请注意,元素必然是可变的,因为选择驱动文档的转换!
安装
如果您使用NPM, npm install d3-selection
。否则,请下载最新版本。您也可以直接从d3js.org加载,作为独立库或作为D3 4.0的一部分。支持AMD,CommonJS和vanilla环境。在vanilla中,d3
全球出口:
<script src="https://d3js.org/d3-selection.v1.min.js"></script>
<script>
var div = d3.selectAll("div");
</script>
在浏览器中尝试d3选择。
API参考
选择元素
选择方法接受W3C选择器字符串,例如.fancy
选择具有类花哨的元素,或div
选择DIV元素。选择方法有两种形式:select和selectAll:前者只选择第一个匹配元素,而后者按文档顺序选择所有匹配元素。顶级选择方法d3.select和d3.selectAll查询整个文档; 部分选取方法,selection.select和 selection.selectAll,限制选择到所选择的元素的后代。
# d3.selection() <>
选择根元素document.documentElement
。此函数还可用于测试选择(instanceof d3.selection
)或扩展选择原型。例如,要添加检查复选框的方法:
d3.selection.prototype.checked = function(value) {
return arguments.length < 1
? this.property("checked")
: this.property("checked", !!value);
};
然后使用:
d3.selectAll("input[type=checkbox]").checked(true);
# d3.select(selector) <>
选择与指定选择器字符串匹配的第一个元素。如果没有元素与选择器匹配,则返回空选择。如果多个元素与选择器匹配,则仅选择第一个匹配元素(按文档顺序)。例如,要选择第一个锚元素:
var anchor = d3.select("a");
如果选择器不是字符串,则选择指定的节点; 如果您已经拥有对节点的引用,例如this
在事件侦听器或全局范围内,则此选项非常有用document.body
。例如,要将单击的段落设置为红色:
d3.selectAll("p").on("click", function() {
d3.select(this).style("color", "red");
});
选择与指定选择器字符串匹配的所有元素。将按文档顺序(从上到下)选择元素。如果文档中没有元素与选择器匹配,或者选择器为null或未定义,则返回空选择。例如,要选择所有段落:
var paragraph = d3.selectAll("p");
如果选择器不是字符串,而是选择指定的节点数组; 如果您已经拥有对节点的引用,例如this.childNodes
在事件侦听器或全局范围内,那么这很有用document.links
。节点可以替代地是诸如a NodeList
或的伪阵列arguments
。例如,要将所有链接着色为红色:
d3.selectAll(document.links).style("color", "red");
# selection.select(selector) <>
对于每个选定的元素,选择与指定的选择器字符串匹配的第一个后代元素。如果没有元素与当前元素的指定选择器匹配,则当前索引处的元素在返回的选择中将为null。(如果选择器为null,则返回选择中的每个元素都将为空,从而导致选择为空。)如果当前元素具有关联数据,则此数据将传播到相应的选定元素。如果多个元素与选择器匹配,则仅选择文档顺序中的第一个匹配元素。例如,要选择每个段落中的第一个粗体元素:
var b = d3.selectAll("p").select("b");
如果选择器是一个函数,则按顺序计算每个选定元素,传递当前数据(d),当前索引(i)和当前组(节点),并将其作为当前DOM元素(节点 [ i ])。它必须返回一个元素,如果没有匹配元素,则返回null。例如,要选择每个段落的上一个兄弟:
var previous = d3.selectAll("p").select(function() {
return this.previousElementSibling;
});
与选择 .selectAll不同,selection .select不会影响分组:它保留现有的组结构和索引,并将数据(如果有的话)传播给选定的子组。分组在数据连接中起着重要作用。有关此主题的更多信息,请参阅嵌套选择和如何选择。
# selection.selectAll(selector) <>
对于每个选定的元素,选择与指定的选择器字符串匹配的后代元素。返回选择中的元素按此选择中的相应父节点分组。如果没有元素与当前元素的指定选择器匹配,或者选择器为null,则当前索引处的组将为空。所选元素不会从此选择中继承数据; 使用selection .data将数据传播给子节点。例如,要选择每个段落中的粗体元素:
var b = d3.selectAll("p").selectAll("b");
如果选择器是一个函数,则按顺序计算每个选定元素,传递当前数据(d),当前索引(i)和当前组(节点),并将其作为当前DOM元素(节点 [ i ])。它必须返回一个元素数组(或一个伪数组,如NodeList),如果没有匹配的元素,则返回空数组。例如,要选择每个段落的上一个和下一个兄弟节点:
var sibling = d3.selectAll("p").selectAll(function() {
return [
this.previousElementSibling,
this.nextElementSibling
];
});
与选择 .select不同,选择 .selectAll确实会影响分组:每个选定的后代都按原始选择中的父元素分组。分组在数据连接中起着重要作用。有关此主题的更多信息,请参阅嵌套选择和如何选择。
# selection.filter(filter) <>
过滤选择,返回仅包含指定过滤器为true 的元素的新选择。该过滤器可以或者作为选择字符串或函数来指定。如果过滤器是一个函数,则按顺序计算每个选定元素的值,传递当前数据(d),当前索引(i)和当前组(节点),并将其作为当前DOM元素(节点 [ i ])。
例如,要过滤选择的表行以仅包含偶数行:
var even = d3.selectAll("tr").filter(":nth-child(even)");
这大致相当于直接使用d3.selectAll,尽管索引可能不同:
var even = d3.selectAll("tr:nth-child(even)");
同样,使用一个函数:
var even = d3.selectAll("tr").filter(function(d, i) { return i & 1; });
或使用selection.select:
var even = d3.selectAll("tr").select(function(d, i) { return i & 1 ? this : null; })
请注意,:nth-child
伪类是基于一的索引而不是从零开始的索引。而且,上述滤波器功能的含义并不完全相同:nth-child
; 它们依赖于选择索引而不是DOM中前面的兄弟元素的数量。
返回的筛选选择会保留此选择的父项,但与array.filter,一样,它不会保留索引,因为某些元素可能会被删除; 如果需要,使用selection .select保留索引。
返回将此选择与指定的其他选择合并的新选择。返回的选择与此选择具有相同数量的组和相同的父项。此选择中的任何缺少(null)元素都将使用指定选择中的相应元素(如果存在(非空))填充。(如果其他选择包含其他组或父项,则会忽略它们。)
通过selection.join在内部使用此方法来合并绑定数据后的输入和更新选择。您也可以明确合并。例如:
var circle = svg.selectAll("circle").data(data) // UPDATE
.style("fill", "blue");
circle.exit().remove(); // EXIT
circle = circle.enter().append("circle") // ENTER
.style("fill", "green")
.merge(circle) // ENTER + UPDATE
.style("stroke", "black");
有关更多信息,请参阅selection.data
但是,此方法不用于连接任意选择:如果此选择和指定的其他选择都在同一索引处具有(非空)元素,则在合并中返回此选择的元素,并忽略其他选择的元素。
# d3.matcher(selector) <>
给定指定的选择器,返回一个函数,如果this
element 匹配指定的选择器,则返回true 。此方法在选择 .filter内部使用。例如,这个:
var div = selection.filter("div");
相当于:
var div = selection.filter(d3.matcher("div"));
(虽然D3不是兼容层,但由于最近element.matches的标准化,此实现确实支持供应商前缀实现。)
# d3.selector(selector) <>
给定指定的选择器,返回一个函数,该函数返回this
与指定选择器匹配的元素的第一个后代。此方法在内部通过selection.select使用。例如,这个:
var div = selection.select("div");
相当于:
var div = selection.select(d3.selector("div"));
给定指定的选择器,返回一个函数,该函数返回this
与指定选择器匹配的元素的所有后代。此方法在内部通过selection.selectAll使用。例如,这个:
var div = selection.selectAll("div");
相当于:
var div = selection.selectAll(d3.selectorAll("div"));
# d3.window(node) <>
返回指定节点的所有者窗口。如果node是节点,则返回所有者文档的默认视图; 如果node是文档,则返回其默认视图; 否则返回节点。
# d3.style(node, name) <>
返回具有指定节点的指定名称的style属性的值。如果节点具有指定名称的内联样式,则返回其值; 否则,返回计算的属性值。另请参见selection .style。
修改元素
选择元素后,使用选择的转换方法来影响文档内容。例如,要设置锚元素的名称属性和颜色样式:
d3.select("a")
.attr("name", "fred")
.style("color", "red");
要试验选择,请访问d3js.org并打开浏览器的开发者控制台!(在Chrome中,使用⌥⌘J打开控制台。)选择元素,然后检查返回的选择以查看选择了哪些元素以及如何对它们进行分组。调用选择方法并查看页面内容如何更改。
# selection.attr(name[, value]) <>
如果指定了值,则将具有指定名称的属性设置为所选元素上的指定值,并返回此选择。如果值是常量,则所有元素都被赋予相同的属性值; 否则,如果值是一个函数,则按顺序计算每个选定元素的值,传递当前数据(d),当前索引(i)和当前组(节点),并将其作为当前DOM element(nodes [ i ])。然后使用函数的返回值来设置每个元素的属性。空值将删除指定的属性。
如果未指定值,则返回选择中第一个(非null)元素的指定属性的当前值。仅当您知道选择包含一个元素时,这通常很有用。
指定的名称可以具有名称空间前缀,例如在XLink名称空间中xlink:href
指定href
属性。见命名空间为支持的名字空间的地图; 可以通过添加到地图来注册其他名称空间。
# selection.classed(names[, value]) <>
如果指定了值,则通过设置属性或修改属性来指定或取消分配所选元素上的指定CSS类名,并返回此选择。指定的名称是一个空格分隔的类名称字符串。例如,要分配类和选定的元素:class
classList
foo
bar
selection.classed("foo bar", true);
如果该值是真实的,则为所有元素分配指定的类; 否则,这些类是未分配的。如果值是一个函数,则按顺序计算每个选定元素的值,传递当前数据(d),当前索引(i)和当前组(节点),并将其作为当前DOM元素(节点 [ i ])。然后,函数的返回值用于为每个元素分配或取消分配类。例如,要将类foo随机地与所选元素的一半相关联:
selection.classed("foo", function() { return Math.random() > 0.5; });
如果未指定值,则当且仅当第一个(非null)所选元素具有指定的类时,才返回true 。仅当您知道选择包含一个元素时,这通常很有用。
# selection.style(name[, value[, priority]]) <>
如果指定了值,则将具有指定名称的style属性设置为所选元素上的指定值,并返回此选择。如果值是常量,则所有元素都被赋予相同的样式属性值; 否则,如果值是一个函数,则按顺序计算每个选定元素的值,传递当前数据(d),当前索引(i)和当前组(节点),并将其作为当前DOM元素(节点 [ i])。然后使用函数的返回值来设置每个元素的样式属性。null值将删除style属性。还可以指定可选优先级,可以是null或字符串important
(不带感叹号)。
如果未指定值,则返回选择中第一个(非null)元素的指定样式属性的当前值。当前值定义为元素的内联值(如果存在),否则定义为其计算值。仅当您知道选择包含一个元素时,才能访问当前样式值。
警告:与许多SVG属性不同,CSS样式通常具有关联的单元。例如,3px
是有效的笔画宽度属性值,而3
不是。有些浏览器隐式地将px
(像素)单元分配给数值,但并非所有浏览器都这样做:例如,IE会抛出“无效参数”错误!
# selection.property(name[, value]) <>
某些HTML元素具有使用属性或样式无法寻址的特殊属性,例如表单字段的文本value
和复选框的checked
布尔值。使用此方法获取或设置这些属性。
如果指定了值,则将具有指定名称的属性设置为所选元素上的指定值。如果该值是常量,则所有元素都被赋予相同的属性值; 否则,如果值是一个函数,则按顺序计算每个选定元素的值,传递当前数据(d),当前索引(i)和当前组(节点),并将其作为当前DOM element(nodes [ i ])。然后使用函数的返回值来设置每个元素的属性。空值将删除指定的属性。
如果未指定值,则返回选择中第一个(非null)元素的指定属性的值。仅当您知道选择包含一个元素时,这通常很有用。
# selection.text([value]) <>
如果指定了值,则将文本内容设置为所有选定元素上的指定值,替换任何现有子元素。如果值是常量,则所有元素都被赋予相同的文本内容; 否则,如果值是一个函数,则按顺序计算每个选定元素的值,传递当前数据(d),当前索引(i)和当前组(节点),并将其作为当前DOM element(nodes [ i ])。然后使用函数的返回值来设置每个元素的文本内容。空值将清除内容。
如果未指定值,则返回选择中第一个(非null)元素的文本内容。仅当您知道选择包含一个元素时,这通常很有用。
# selection.html([value]) <>
如果指定了值,则将内部HTML设置为所有选定元素上的指定值,替换任何现有子元素。如果值是常量,那么所有元素都被赋予相同的内部HTML; 否则,如果值是一个函数,则按顺序计算每个选定元素的值,传递当前数据(d),当前索引(i)和当前组(节点),并将其作为当前DOM element(nodes [ i ])。然后使用函数的返回值来设置每个元素的内部HTML。空值将清除内容。
如果未指定值,则返回选择中第一个(非null)元素的内部HTML。仅当您知道选择包含一个元素时,这通常很有用。
使用selection.append或selection.insert来创建数据驱动的内容; 此方法适用于需要一点HTML的情况,例如丰富的格式。此外,仅在HTML元素上支持选择 .html。SVG元素和其他非HTML元素不支持innerHTML属性,因此与选择 .html 不兼容。考虑使用XMLSerializer将DOM子树转换为文本。另请参阅innersvg polyfill,它提供了一个shim来支持SVG元素的innerHTML属性。
# selection.append(type) <>
如果指定的类型是字符串,则将此类型的新元素(标记名称)作为每个所选元素的最后一个子元素添加,或者在更新选择中的下一个兄弟元素之前添加(如果这是输入选择)。输入选择的后一种行为允许您按照与新绑定数据一致的顺序将元素插入DOM; 但请注意,如果更新元素更改顺序(即,如果新数据的顺序与旧数据不一致),则仍可能需要选择 .order。
如果指定的类型是一个函数,则按顺序为每个选定元素计算它,传递当前数据(d),当前索引(i)和当前组(节点),并将其作为当前DOM元素(nodes [ i ])。此函数应返回要追加的元素。(该函数通常会创建一个新元素,但它可能会返回一个现有元素。)例如,要将DIV元素附加到每个段落:
d3.selectAll("p").append("div");
这相当于:
d3.selectAll("p").append(function() { return document.createElement("div"); });
这相当于:
d3.selectAll("p").select(function() {
return this.appendChild(document.createElement("div"));
});
在这两种情况下,此方法都返回包含附加元素的新选择。每个新元素都以与selection .select相同的方式继承当前元素的数据(如果有)。
指定的名称可以具有名称空间前缀,例如在SVG名称空间中svg:text
指定text
属性。见命名空间为支持的名字空间的地图; 可以通过添加到地图来注册其他名称空间。如果未指定名称空间,则名称空间将从父元素继承; 或者,如果名称是已知前缀之一,则将使用相应的命名空间(例如,svg
暗示svg:svg
)。
# selection.insert(type[, before]) <>
如果指定的类型是字符串,则在匹配指定的before选择器的第一个元素之前,为每个选定元素插入此类型的新元素(标记名称)。例如,before选择器:first-child
将在第一个子节点之前添加节点。如果未指定before,则默认为null。(要按照与绑定数据一致的顺序追加元素,请使用selection .append。)
两个类型和之前可以替代地指定为其中为每个选择的元件进行评价,为了功能,正在传递的当前数据(d),当前指数(我),和当前组(节点),与此作为当前DOM元素(nodes [ i ])。的类型函数应该返回要插入的元件; 在之前函数返回的元素应该被插入之后的子元素。例如,要将DIV元素附加到每个段落
d3.selectAll("p").insert("div");
这相当于:
d3.selectAll("p").insert(function() {
return document.createElement("div");
});
这相当于:
d3.selectAll("p").select(function() {
return this.insertBefore(document.createElement("div"), null);
});
在这两种情况下,此方法都返回包含附加元素的新选择。每个新元素都以与selection .select相同的方式继承当前元素的数据(如果有)。
指定的名称可以具有名称空间前缀,例如在SVG名称空间中svg:text
指定text
属性。见命名空间为支持的名字空间的地图; 可以通过添加到地图来注册其他名称空间。如果未指定名称空间,则名称空间将从父元素继承; 或者,如果名称是已知前缀之一,则将使用相应的命名空间(例如,svg
暗示svg:svg
)。
# selection.remove() <>
从文档中删除选定的元素。返回此选择(已删除的元素),这些选择现在与DOM分离。目前没有专门的API将已删除的元素添加回文档; 但是,您可以将函数传递给selection.append或selection.insert以重新添加元素。
# selection.clone([deep]) <>
在所选元素后面紧跟插入所选元素的克隆,并返回新添加克隆的选择。如果深度是真实的,那么所选元素的后代节点也将被克隆。否则,只会克隆元素本身。相当于:
selection.select(function() {
return this.parentNode.insertBefore(this.cloneNode(deep), this.nextSibling);
});
# selection.sort(compare) <>
返回一个新选择,其中包含根据compare函数排序的此选择中每个组的副本。排序后,重新插入元件,以(每所得顺序相匹配selection.order)。
比较函数默认为升序,传递两个元素的数据a和b进行比较。它应返回负值,正值或零值。如果是否定的,那么a应该在b之前; 如果是肯定的,那么a应该在b之后; 否则,a和b被认为是相等的,并且顺序是任意的。
请注意,排序不保证稳定; 但是,它保证与您的浏览器在数组上的内置排序方法具有相同的行为。
# selection.order() <>
将元素重新插入到文档中,以使每个组的文档顺序与选择顺序匹配。这相当于调用 selection.sort如果数据已经排序,但速度要快得多。
# selection.raise() <>
按顺序重新插入每个选定元素作为其父元素的最后一个子元素。相当于:
selection.each(function() {
this.parentNode.appendChild(this);
});
# selection.lower() <>
按顺序重新插入每个选定元素作为其父元素的第一个子元素。相当于:
selection.each(function() {
this.parentNode.insertBefore(this, this.parentNode.firstChild);
});
# d3.create(name) <>
给定指定的元素名称,返回包含当前文档中给定名称的分离元素的单元素选择。
# d3.creator(name) <>
给定指定的元素名称,返回一个创建给定名称元素的函数,假设它this
是父元素。通过选择selection.append和选择selection.insert在内部使用此方法来创建新元素。例如,这个:
selection.append("div");
相当于:
selection.append(d3.creator("div"));
有关支持的名称空间前缀的详细信息,请参阅名称空间,例如SVG元素。
加入数据
有关D3数据连接的介绍,请参阅Thinking with Joins。另请参阅常规更新模式示例。
# selection.data([data[, key]]) <>
使用所选元素绑定指定的数据数组,返回表示更新选择的新选择:成功绑定到数据的元素。还定义了返回选择的输入和退出选择,可用于添加或删除与新数据对应的元素。指定的数据是任意值的数组(例如,数字或对象),或返回每个组的值数组的函数。将数据分配给元素时,它将存储在属性中__data__
,从而使数据“粘滞”并在重新选择时可用。
该数据被指定为每个组中选择。如果选择有多个组(例如d3.selectAll后跟selection.selectAll),则通常应将数据指定为函数。将按顺序为每个组评估此函数,传递组的父数据(d,可能是未定义的),组索引(i)和选择的父节点(节点),并将其作为组的父元素。
结合selection.join(或更明确地selection.enter, selection.exit, selection.append 和selection.remove),选择 .data可用于输入,更新和退出元素以匹配数据。例如,要从数字矩阵创建HTML表:
var matrix = [
[11975, 5871, 8916, 2868],
[ 1951, 10048, 2060, 6171],
[ 8010, 16145, 8090, 8045],
[ 1013, 990, 940, 6907]
];
var tr = d3.select("body")
.append("table")
.selectAll("tr")
.data(matrix)
.join("tr");
var td = tr.selectAll("td")
.data(function(d) { return d; })
.join("td")
.text(function(d) { return d; });
在此示例中,数据函数是标识函数:对于每个表行,它返回数据矩阵中的相应行。
如果一个键未指定功能,则在第一数据的数据被分配给第一选择的元素,第二数据至该第二选择的元素,依此类推。甲关键功能可以被指定为控制哪些数据被分配给哪个元素,替换默认加入逐索引,通过计算每个数据和元件的串标识符。为每个选定的元素评估此关键函数,按顺序传递当前数据(d),当前索引(i)和当前组(节点),并将其作为当前DOM元素(节点 [ i]]); 返回的字符串是元素的键。键功能,然后还评价了在每一个新的基准数据,正在传递的当前数据(d),当前指数(我),以及该组的新数据,与此作为组的父DOM元素; 返回的字符串是数据的键。给定键的数据被分配给具有匹配键的元素。如果多个元素具有相同的键,则将重复的元素放入出口选择中; 如果多个数据具有相同的密钥,则将重复数据放入输入选择中。
例如,鉴于此文件:
<div id="Ford"></div>
<div id="Jarrah"></div>
<div id="Kwon"></div>
<div id="Locke"></div>
<div id="Reyes"></div>
<div id="Shephard"></div>
您可以按键加入数据,如下所示:
var data = [
{name: "Locke", number: 4},
{name: "Reyes", number: 8},
{name: "Ford", number: 15},
{name: "Jarrah", number: 16},
{name: "Shephard", number: 23},
{name: "Kwon", number: 42}
];
d3.selectAll("div")
.data(data, function(d) { return d ? d.name : this.id; })
.text(function(d) { return d.number; });
此示例键函数使用数据d(如果存在),否则返回到元素的id属性。由于这些元素先前未绑定到数据,因此在对所选元素计算关键函数时,数据d为空,而在对新数据计算关键函数时,数据为非空。
该更新和输入选择在数据顺序返回,而退出选择保留之前加入选择顺序。如果指定了键功能,则选择中元素的顺序可能与文档中的顺序不匹配; 根据需要使用selection .order或selection .sort。有关键函数如何影响连接的更多信息,请参阅条形图,第2部分和对象常量。
如果未指定数据,则此方法返回所选元素的数据数组。
此方法不能用于清除绑定数据; 使用selection.datum代替。
# selection.join(enter[, update][, exit]) <>
根据需要追加,删除和重新排序元素,以匹配先前由
selection.data绑定的数据,返回合并的输入和更新选择。此方法是更明确selection.enter,selection.exit,selection.append和selection.remove)的替代方法。例如:
svg.selectAll("circle")
.data(data)
.join(
enter => enter.append("circle").attr("fill", "green"),
update => update.attr("fill", "blue")
)
.attr("stroke", "black");
有关更多示例,请参阅selection.join Observable笔记本。
这相当于一般更新模式:
var circle = svg.selectAll("circle") // 1
.data(data) // 2
.attr("fill", "blue"); // 3
circle.exit().remove(); // 4
circle = circle.enter().append("circle") // 5, 9
.attr("fill", "green") // 6
.merge(circle) // 7
.order() // 8
.attr("stroke", "black"); // 9
将其分解为不连续的步骤:
- 任何现有的圆(属于的后代
svg
选择)的选择。 - 这些圈子连接到新的
data
,返回匹配的圈子:更新选择。 - 这些更新圈子被给予蓝色填充。
- 将删除与新数据不匹配的任何现有圆圈- 退出选择。
- 对于与任何现有圆圈不匹配的任何新数据,将附加新圆圈:输入选择。
- 这些进入的圆圈被赋予绿色填充。
- 创建表示输入和更新圆的并集的新选择。
- 这些输入和更新圈子被重新排序以匹配数据(如果需要)。
- 圆圈呈黑色划线。
- 圆圈存储在变量中
circle
。
如前面段落所述,“匹配”逻辑由传递给选择 .data 的键函数确定; 由于在上面的代码示例中没有使用键函数,因此元素和数据通过索引连接。
返回输入选择:占位符节点,用于选择中没有相应DOM元素的每个数据。(对于selection.data未返回的选择,输入选择为空。)
输入选择通常用于创建与新数据相对应的“缺失”元素。例如,要从数字数组创建DIV元素:
var div = d3.select("body")
.selectAll("div")
.data([4, 8, 15, 16, 23, 42])
.enter().append("div")
.text(function(d) { return d; });
如果正文最初为空,则上面的代码将创建六个新的DIV元素,按顺序将它们附加到正文,并将其文本内容指定为关联的(字符串强制)数字:
<div>4</div>
<div>8</div>
<div>15</div>
<div>16</div>
<div>23</div>
<div>42</div>
从概念上讲,输入选择的占位符是指向父元素的指针(在本例中为文档主体)。输入选择通常仅暂时用于附加元素,并且通常在附加后与更新选择合并,使得修改可以应用于输入和更新元素。
# selection.exit() <>
返回退出选择:选择中没有找到新数据的现有DOM元素。(对于 selection.data未返回的选择,退出选择为空。)
退出选择通常用于删除与旧数据相对应的“多余”元素。例如,要使用新的数字数组更新先前创建的DIV元素:
div = div.data([1, 2, 4, 8, 16, 32], function(d) { return d; });
由于指定了键函数(作为标识函数),并且新数据包含与文档中现有元素匹配的数字[4,8,16],因此更新选择包含三个DIV元素。将这些元素保留为原样,我们可以使用输入选择为[1,2,32]添加新元素:
div.enter().append("div").text(function(d) { return d; });
同样,要删除现有元素[15,23,42]:
div.exit().remove();
现在文档正文如下所示:
<div>1</div>
<div>2</div>
<div>4</div>
<div>8</div>
<div>16</div>
<div>32</div>
DOM元素的顺序与数据的顺序匹配,因为旧数据的顺序和新数据的顺序是一致的。如果新数据的顺序不同,请使用selection.order重新排序DOM中的元素。有关数据连接的更多信息,请参阅常规更新模式示例线程。
# selection.datum([value]) <>
获取或设置每个选定元素的绑定数据。与selection.data不同,此方法不计算连接,也不影响索引或输入和退出选择。
如果指定了值,则将元素的绑定数据设置为所有选定元素上的指定值。如果该值是常量,则所有元素都被赋予相同的数据; 否则,如果值是一个函数,则按顺序计算每个选定元素的值,传递当前数据(d),当前索引(i)和当前组(节点),并将其作为当前DOM element(nodes [ i ])。然后,该函数用于设置每个元素的新数据。空值将删除绑定数据。
如果未指定值,则返回选择中第一个(非null)元素的bound数据。仅当您知道选择包含一个元素时,这通常很有用。
此方法对于访问HTML5 自定义数据属性很有用。例如,给出以下要素:
<ul id="list">
<li data-username="shawnbot">Shawn Allen</li>
<li data-username="mbostock">Mike Bostock</li>
</ul>
您可以通过将每个元素的数据设置为内置数据集属性来公开自定义数据属性:
selection.datum(function() { return this.dataset; })
处理事件
对于交互,选择允许监听和分派事件。
# selection.on(typenames[, listener[, options]]) <>
为指定的事件类型名称的每个选定元素添加或删除侦听器。所述typenames是一个字符串事件类型,如,,或; 可以使用浏览器支持的任何DOM事件类型。类型可以可选地后跟句点()和名称; 可选名称允许注册多个回调以接收相同类型的事件,例如和。要指定多个类型名称,请使用空格分隔类型名称,例如或。click
mouseover
submit
.
click.foo
click.bar
input change
click.foo click.bar
当在所选元素上调度指定事件时,将为元素评估指定的侦听器,传递当前数据(d),当前索引(i)和当前组(节点),并将其作为当前值DOM元素(nodes [ i ])。监听器总是看到其元素的最新数据,但索引是选择的属性,并且在分配监听器时是固定的; 更新索引,重新分配监听器。要在侦听器中访问当前事件,请使用d3.event。
如果事件侦听器先前已在所选元素上注册了相同的类型名称,则在添加新侦听器之前将删除旧侦听器。要删除侦听器,请将null作为侦听器传递。要删除给定名称的所有侦听器,请将null作为侦听器并.foo
作为typename传递,其中foo
名称为; 删除所有没有名称的侦听器,指定.
为typename。
可选的选项对象可以指定有关事件侦听器的特征,例如它是捕获还是被动; 请参阅element.addEventListener。
如果收听者未指定,返回指定事件的当前分配的侦听类型名称的第一个(非空)选择的元素上,如果有的话。如果指定了多个类型名,则返回第一个匹配的侦听器。
# selection.dispatch(type[, parameters]) <>
按顺序将指定类型的自定义事件调度到每个选定元素。可以指定可选参数映射以设置事件的其他属性。它可能包含以下字段:
bubbles
- 如果为true,则以反向树顺序将事件分派给祖先。cancelable
- 如果为true,则允许事件 .preventDefault。detail
- 与事件相关的任何自定义数据。
如果参数是一个函数,则按顺序计算每个选定元素的值,传递当前数据(d),当前索引(i)和当前组(节点),并将其作为当前DOM元素(节点) [ i ])。它必须返回当前元素的参数映射。
# d3.event
当前event,如果有的话。这是在调用事件侦听器期间设置的,并在侦听器终止后重置。使用此访问标准活动领域,如event.timeStamp以及诸如方法event .preventDefault。虽然您可以使用本机event .pageX和event .pageY,但使用d3.mouse,d3.touch或d3.touches将事件位置转换为接收事件的容器的本地坐标系通常更方便。
如果您使用Babel,Webpack或其他ES6到ES5捆绑器,请注意d3.event的值在事件期间会发生变化!导入d3.event必须是实时绑定,因此您可能需要将捆绑程序配置为从D3的ES6模块而不是从生成的UMD包导入; 并非所有捆绑商都观察到jsnext:main。还要注意与 window.event全局的冲突。
# d3.customEvent(event, listener[, that[, arguments]]) <>
调用指定监听器,使用指定的这 this
方面并通过指定的参数,如果有的话。在调用期间,d3.event设置为指定的事件 ; 在侦听器返回(或抛出错误)之后,d3.event将恢复为其先前的值。此外,将事件 .sourceEvent 设置为d3.event的先前值,允许自定义事件保留对原始本机事件的引用。返回侦听器返回的值。
# d3.mouse(container) <>
返回当前事件相对于指定容器的x和y坐标。容器可以是HTML或SVG容器元素,例如G元素或SVG元素。坐标以数字[ x,y ] 的双元素数组的形式返回。
# d3.touch(container[, touches], identifier) <>
返回触摸的x和y坐标,其中指定的标识符与当前事件相关的指定标识符相对于指定的容器。容器可以是HTML或SVG容器元素,例如G元素或SVG元素。坐标以数字[ x,y ] 的双元素数组的形式返回。如果存在与指定的标识符没有触摸触摸,则返回null; 这对于忽略只有一些触摸移动的touchmove事件非常有用。如果未指定touches,则默认为当前事件changedTouches属性。
# d3.touches(container[, touches]) <>
返回与当前事件关联的触摸相对于指定容器的x和y坐标。容器可以是HTML或SVG容器元素,例如G元素或SVG元素。坐标以数组[[ x1,y1 ],[ x2,y2 ],...] 的双元素数组的数组的形式返回。如果未指定touches,则默认为当前事件的touches属性。
# d3.clientPoint(container, event) <>
返回指定事件相对于指定容器的x和y坐标。(事件也可以是触摸。)容器可以是HTML或SVG容器元素,例如G元素或SVG元素。坐标以数字[ x,y ] 的双元素数组的形式返回。
控制流
对于高级用法,选择提供自定义控制流的方法。
# selection.each(function) <>
按顺序为每个选定元素调用指定函数,传递当前数据(d),当前索引(i)和当前组(节点),并将其作为当前DOM元素(nodes [ i ])。此方法可用于为每个选定元素调用任意代码,对于创建同时访问父数据和子数据的上下文非常有用,例如:
parent.each(function(p, j) {
d3.select(this)
.selectAll(".child")
.text(function(d, i) { return "child " + d.name + " of " + p.name; });
});
有关示例,请参阅Sized Donut Multiples。
# selection.call(function[, arguments…]) <>
只调用指定的函数一次,传入此选择以及任何可选参数。返回此选择。这相当于手动调用函数,但有助于方法链接。例如,要在可重用函数中设置多个样式:
function name(selection, first, last) {
selection
.attr("first-name", first)
.attr("last-name", last);
}
现在说:
d3.selectAll("div").call(name, "John", "Snow");
这大致相当于:
name(d3.selectAll("div"), "John", "Snow");
唯一的区别是,选择 .CALL总是返回的选择,而不是所谓的返回值函数,name
。
如果此选择不包含(非null)元素,则返回true。
返回此选择中所有(非null)元素的数组。
返回此选择中的第一个(非null)元素。如果选择为空,则返回null。
返回此选择中的元素总数。
局部变量
D3 locals允许您定义独立于数据的本地状态。例如,在渲染小倍数的时间序列数据时,您可能希望所有图表使用相同的x-scale,但需要使用不同的y -scales来比较每个度量标准的相对性能。D3 locals由DOM元素确定范围:在set上,值存储在给定元素上; 在get上,从给定元素或定义它的最近祖先检索该值。
# d3.local() <>
声明一个新的局部变量。例如:
var foo = d3.local();
比如var
,每个地方都是一个独特的象征性参考; 不同的var
是,每个局部的值也由DOM确定范围。
# local.set(node, value) <>
设置此本地指定的值节点的值,并返回指定的值。这通常使用selection.each执行:
selection.each(function(d) { foo.set(this, d.value); });
如果您只是设置单个变量,请考虑使用selection .property:
selection.property(foo, function(d) { return d.value; });
# local.get(node) <>
返回指定节点上此local的值。如果节点未定义此local,则返回定义它的最近祖先的值。如果没有祖先定义此本地,则返回undefined。
# local.remove(node) <>
从指定节点删除此本地值。如果节点在删除之前定义了此本地,则返回true,否则返回false。如果祖先也定义了这个本地,那么这些定义不受影响,因此local.get仍然会返回继承的值。
# local.toString() <>
返回此本地的自动生成的标识符。这是用于在元素上存储本地值的属性的名称,因此您还可以使用元素 [ local ]或使用selection .property来设置或获取本地值。
命名空间
XML命名空间很有趣!对?幸运的是,你可以忽略它们。
限定指定的名称,该名称可能有也可能没有名称空间前缀。如果名称包含冒号(:
),则冒号前的子字符串将被解释为名称空间前缀,该前缀必须在d3.namespaces中注册。返回描述完整命名空间URL和本地名称的对象space
和local
属性。例如:
d3.namespace("svg:text"); // {space: "http://www.w3.org/2000/svg", local: "text"}
如果名称不包含冒号,则此函数仅返回输入名称。
# d3.namespaces <>
已注册名称空间前缀的映射。初始值是:
{
svg: "http://www.w3.org/2000/svg",
xhtml: "http://www.w3.org/1999/xhtml",
xlink: "http://www.w3.org/1999/xlink",
xml: "http://www.w3.org/XML/1998/namespace",
xmlns: "http://www.w3.org/2000/xmlns/"
}
可以根据需要分配附加前缀以在其他命名空间中创建元素或属性。