Skip to content

选择元素

🌐 Selecting elements

“选择”是来自 DOM 的一组元素。通常,这些元素是通过选择器来识别的,例如使用 .fancy 选择具有 fancy 类的元素,或使用 div 选择 DIV 元素。

🌐 A selection is a set of elements from the DOM. Typically these elements are identified by selectors such as .fancy for elements with the class fancy, or div to select DIV elements.

选择方法有两种形式,selectselectAll:前者只选择第一个匹配的元素,而后者按文档顺序选择所有匹配的元素。顶层选择方法 d3.selectd3.selectAll 查询整个文档;子选择方法 selection.selectselection.selectAll 将选择限制在已选择元素的后代中。还有 selection.selectChildselection.selectChildren 用于直接子元素。

🌐 Selection methods come in two forms, select and selectAll: the former selects only the first matching element, while the latter selects all matching elements in document order. The top-level selection methods, d3.select and d3.selectAll, query the entire document; the subselection methods, selection.select and selection.selectAll, restrict selection to descendants of the selected elements. There is also selection.selectChild and selection.selectChildren for direct children.

按照惯例,返回当前选择的选择方法,例如 selection.attr,使用四个空格缩进,而返回新选择的方法仅使用两个空格。这有助于通过让它们从链条中突出出来,从而揭示上下文的变化:

🌐 By convention, selection methods that return the current selection such as selection.attr use four spaces of indent, while methods that return a new selection use only two. This helps reveal changes of context by making them stick out of the chain:

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

selection()

· 选择根元素,document.documentElement

js
const root = d3.selection();

此函数也可用于测试选择项(instanceof d3.selection)或扩展选择原型。例如,添加一个方法来检查复选框:

🌐 This function can also be used to test for selections (instanceof d3.selection) or to extend the selection prototype. For example, to add a method to check checkboxes:

js
d3.selection.prototype.checked = function(value) {
  return arguments.length < 1
      ? this.property("checked")
      : this.property("checked", !!value);
};

然后使用:

🌐 And then to use:

js
d3.selectAll("input[type=checkbox]").checked(true);

select(selector)

来源 · 选择与指定的 selector 字符串匹配的第一个元素。

js
const svg = d3.select("#chart");

如果没有元素匹配 selector,则返回一个空的选择。如果多个元素匹配 selector,则只会选择第一个匹配的元素(按文档顺序)。例如,要选择第一个锚点元素:

🌐 If no elements match the selector, returns an empty selection. If multiple elements match the selector, only the first matching element (in document order) will be selected. For example, to select the first anchor element:

js
const anchor = d3.select("a");

如果 selector 不是字符串,则改为选择指定的节点;如果你已经有一个节点的引用,例如 document.body,这会很有用。

🌐 If the selector is not a string, instead selects the specified node; this is useful if you already have a reference to a node, such as document.body.

js
d3.select(document.body).style("background", "red");

或者,将点击的段落设置为红色:

🌐 Or, to make a clicked paragraph red:

js
d3.selectAll("p").on("click", (event) => d3.select(event.currentTarget).style("color", "red"));

selectAll(selector)

来源 · 选择所有与指定 selector 字符串匹配的元素。

js
const p = d3.selectAll("p");

元素将按照文档顺序(从上到下)进行选择。如果文档中没有与 selector 匹配的元素,或者 selector 为 null 或 undefined,则返回一个空选择。

🌐 The elements will be selected in document order (top-to-bottom). If no elements in the document match the selector, or if the selector is null or undefined, returns an empty selection.

如果 selector 不是字符串,则选择指定的节点数组;如果你已经有对节点的引用(例如在事件监听器中的 this.childNodes 或全局变量如 document.links),这非常有用。节点也可以是可迭代对象,或者是类似数组的对象,例如 NodeList。例如,要将所有链接染成红色:

🌐 If the selector is not a string, instead selects the specified array of nodes; this is useful if you already have a reference to nodes, such as this.childNodes within an event listener or a global such as document.links. The nodes may instead be an iterable, or a pseudo-array such as a NodeList. For example, to color all links red:

js
d3.selectAll(document.links).style("color", "red");

selection.select(selector)

来源 · 对每个选定的元素,选择与指定的 selector 字符串匹配的第一个后代元素。

js
const b = d3.selectAll("p").select("b"); // the first <b> in every <p>

如果当前元素没有元素匹配指定的选择器,则返回的选择集中当前索引处的元素将为 null。(如果 选择器 为 null,则返回选择集中的每个元素都将为 null,从而导致选择集为空。)如果当前元素有相关数据,则这些数据会传递给对应的选中元素。如果有多个元素匹配选择器,则只会选择文档顺序中第一个匹配的元素。

🌐 If no element matches the specified selector for the current element, the element at the current index will be null in the returned selection. (If the selector is null, every element in the returned selection will be null, resulting in an empty selection.) If the current element has associated data, this data is propagated to the corresponding selected element. If multiple elements match the selector, only the first matching element in document order is selected.

如果 selector 是一个函数,它会对每个被选元素依次进行评估,传入当前的数据 (d)、当前的索引 (i) 和当前的组 (nodes),其中 this 是当前的 DOM 元素 (nodes[i])。它必须返回一个元素,如果没有匹配的元素则返回 null。例如,选择每个段落的前一个兄弟元素:

🌐 If the selector is a function, it is evaluated for each selected element, in order, being passed the current datum (d), the current index (i), and the current group (nodes), with this as the current DOM element (nodes[i]). It must return an element, or null if there is no matching element. For example, to select the previous sibling of each paragraph:

js
const previous = d3.selectAll("p").select(function() {
  return this.previousElementSibling;
});

selection.selectAll 不同,selection.select 不会影响分组:它会保留现有的分组结构和索引,并将数据(如果有的话)传播给被选中的子元素。分组在 数据连接 中起着重要作用。有关此主题的更多信息,请参见 嵌套选择选择的工作原理

🌐 Unlike selection.selectAll, selection.select does not affect grouping: it preserves the existing group structure and indexes, and propagates data (if any) to selected children. Grouping plays an important role in the data join. See Nested Selections and How Selections Work for more on this topic.

小心

selection.select 会将父元素的数据传播到被选中的子元素。

selection.selectAll(selector)

来源 · 对于每个选定的元素,选择与指定的选择器字符串匹配的子元素。

js
const b = d3.selectAll("p").selectAll("b"); // every <b> in every <p>

返回的选择中的元素按其在此选择中的对应父节点分组。如果没有元素匹配当前元素的指定选择器,或者selector为null,则当前索引处的组将为空。选中的元素不会继承此选择中的数据;使用selection.data将数据传播到子元素。

🌐 The elements in the returned selection are grouped by their corresponding parent node in this selection. If no element matches the specified selector for the current element, or if the selector is null, the group at the current index will be empty. The selected elements do not inherit data from this selection; use selection.data to propagate data to children.

如果 selector 是一个函数,它会针对每个选定的元素按顺序进行计算,传入当前数据 (d)、当前索引 (i) 和当前组 (nodes),同时 this 为当前 DOM 元素 (nodes[i])。它必须返回一个元素数组(或可迭代对象,或类似数组的对象,如 NodeList),如果没有匹配的元素,则返回空数组。例如,要选择每个段落的前一个和后一个兄弟元素:

🌐 If the selector is a function, it is evaluated for each selected element, in order, being passed the current datum (d), the current index (i), and the current group (nodes), with this as the current DOM element (nodes[i]). It must return an array of elements (or an iterable, or a pseudo-array such as a NodeList), or the empty array if there are no matching elements. For example, to select the previous and next siblings of each paragraph:

js
const sibling = d3.selectAll("p").selectAll(function() {
  return [
    this.previousElementSibling,
    this.nextElementSibling
  ];
});

selection.select 不同,selection.selectAll 会影响分组:每个被选中的子代都会按原始选择中的父元素进行分组。分组在 数据绑定 中起着重要作用。有关此主题的更多内容,请参阅 嵌套选择选择的工作原理

🌐 Unlike selection.select, selection.selectAll does affect grouping: each selected descendant is grouped by the parent element in the originating selection. Grouping plays an important role in the data join. See Nested Selections and How Selections Work for more on this topic.

selection.filter(filter)

来源 · 过滤选择,返回一个只包含指定过滤器为真的元素的新选择。例如,要过滤一个表格行的选择以只包含偶数行:

js
const even = d3.selectAll("tr").filter(":nth-child(even)");

这大致相当于直接使用 d3.selectAll,尽管索引可能不同:

🌐 This is approximately equivalent to using d3.selectAll directly, although the indexes may be different:

js
const even = d3.selectAll("tr:nth-child(even)");

过滤器可以指定为选择器字符串或函数。如果过滤器是一个函数,它会对每个被选元素依次进行评估,传入当前数据(d)、当前索引(i)和当前组(nodes),并且this指向当前 DOM 元素(nodes[i])。使用函数时:

🌐 The filter may be specified either as a selector string or a function. If the filter is a function, it is evaluated for each selected element, in order, being passed the current datum (d), the current index (i), and the current group (nodes), with this as the current DOM element (nodes[i]). Using a function:

js
const even = d3.selectAll("tr").filter((d, i) => i & 1);

或者使用 selection.select(并避免使用箭头函数,因为需要使用 this 来引用当前元素):

🌐 Or using selection.select (and avoiding an arrow function, since this is needed to refer to the current element):

js
const even = d3.selectAll("tr").select(function(d, i) { return i & 1 ? this : null; });

请注意,:nth-child 伪类是以一为基的索引,而不是以零为基的索引。此外,上述过滤函数的含义与 :nth-child 并不完全相同;它们依赖于选择的索引,而不是 DOM 中前面兄弟元素的数量。

🌐 Note that the :nth-child pseudo-class is a one-based index rather than a zero-based index. Also, the above filter functions do not have precisely the same meaning as :nth-child; they rely on the selection index rather than the number of preceding sibling elements in the DOM.

返回的过滤选择保留了此选择的父元素,但像 array.filter 一样,它不会保留索引,因为某些元素可能会被移除;如果需要保留索引,请使用 selection.select

🌐 The returned filtered selection preserves the parents of this selection, but like array.filter, it does not preserve indexes as some elements may be removed; use selection.select to preserve the index, if needed.

selection.selectChild(selector)

来源 · 返回一个新的选择集,该选择集包含当前选择集中每个元素匹配 selector 的(第一个)子元素。

js
d3.selectAll("p").selectChild("b") // the first <b> child of every <p>

如果未指定 selector,则选择第一个子元素(如果有的话)。如果 selector 被指定为字符串,则选择第一个匹配的子元素(如果有的话)。如果 selector 是一个函数,则按顺序对每个子节点进行评估,该函数将子节点(child)、子节点的索引(i)以及子节点列表(children)作为参数;该方法选择第一个使选择器返回真值的子节点(如果有的话)。

🌐 If no selector is specified, selects the first child (if any). If the selector is specified as a string, selects the first child that matches (if any). If the selector is a function, it is evaluated for each of the children nodes, in order, being passed the child (child), the child’s index (i), and the list of children (children); the method selects the first child for which the selector return truthy, if any.

小心

selection.selectChild 会将父节点的数据传递给被选中的子节点。

selection.selectChildren(selector)

来源 · 返回当前选集中每个元素匹配 selector 的子元素的新选集。如果未指定 selector,则选择所有子元素。如果 selector 被指定为字符串,则选择匹配的子元素(如果有的话)。如果 selector 是一个函数,则对每个子节点按顺序进行评估,并传入子节点 (child)、子节点的索引 (i) 以及子节点列表 (children);该方法选择所有返回真值的子元素。

selection.selection()

来源 · 返回所选内容(与 transition.selection 对称)。

matcher(selector)

来源 · 给定指定的 selector,返回一个函数,如果 this 元素 匹配 指定的选择器,则该函数返回 true。此方法在内部被 selection.filter 使用。例如,这个:

js
const div = selection.filter("div");

等同于:

🌐 Is equivalent to:

js
const div = selection.filter(d3.matcher("div"));

(虽然D3不是兼容层,但由于element.matches最近的标准化,该实现确实支持厂商前缀的实现。)

selector(selector)

来源 · 给定指定的 selector,返回一个函数,该函数返回匹配指定选择器的 this 元素的第一个后代。此方法在内部由 selection.select 使用。例如,这个:

js
const div = selection.select("div");

等同于:

🌐 Is equivalent to:

js
const div = selection.select(d3.selector("div"));

selectorAll(selector)

来源 · 给定指定的 selector,返回一个函数,该函数返回匹配指定选择器的 this 元素的所有子孙元素。此方法在 selection.selectAll 中内部使用。例如,这个:

js
const div = selection.selectAll("div");

等同于:

🌐 Is equivalent to:

js
const div = selection.selectAll(d3.selectorAll("div"));

窗口(节点)

🌐 window(node)

来源 · 返回指定 node 的所属窗口。如果 node 是一个节点,则返回所属文档的默认视图;如果 node 是一个文档,则返回其默认视图;否则返回 node

样式(节点, 名称)

🌐 style(node, name)

来源 · 返回指定 node 的指定 name 样式属性的值。如果 node 拥有指定 name 的内联样式,则返回其值;否则,返回 计算后的属性值。另请参见 selection.style