跳至内容

选择元素

一个选择是 DOM 中的一组元素。通常这些元素通过 选择器 来识别,例如 .fancy 用于具有类fancy 的元素,或者 div 用于选择 DIV 元素。

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

按照惯例,返回当前选择的 selection 方法(如 selection.attr)使用四个空格缩进,而返回新选择的 selection 方法只使用两个空格缩进。这有助于通过突出显示上下文变化来揭示上下文变化。

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)或扩展选择原型。例如,要向选择添加一个方法来检查复选框

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

然后使用

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

select(selector)

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

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

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

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

如果 selector 不是字符串,则选择指定的节点;如果您已经拥有节点的引用(如 document.body),这很有用。

js
d3.select(document.body).style("background", "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 为空或未定义,则返回一个空选择。

如果 selector 不是字符串,则选择指定的节点数组;如果您已经拥有节点的引用(如事件监听器中的 this.childNodes 或全局变量 document.links),这很有用。这些节点可以是可迭代对象,也可以是伪数组,如 NodeList。例如,要将所有链接颜色设置为红色

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。(如果 selector 为 null,则返回选择中的每个元素都将为 null,从而导致选择为空。)如果当前元素具有关联数据,则此数据将传播到相应的选定元素。如果多个元素与选择器匹配,则只选择第一个匹配的元素(按文档顺序)。

如果 selector 是一个函数,则按顺序针对每个选定元素对其进行评估,并传递当前数据 (d)、当前索引 (i) 和当前组 (nodes),其中 this 为当前 DOM 元素 (nodes[i])。它必须返回一个元素,或者如果没有任何匹配的元素,则返回 null。例如,要选择每个段落的上一级同级元素

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

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

警告

selection.select 将父级的数据传播到选定的子元素。

selection.selectAll(selector)

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

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

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

如果 selector 是一个函数,则按顺序针对每个选定元素对其进行评估,并传递当前数据 (d)、当前索引 (i) 和当前组 (nodes),其中 this 为当前 DOM 元素 (nodes[i])。它必须返回一个元素数组(或可迭代对象,或伪数组,如 NodeList),或者如果没有匹配的元素,则返回空数组。例如,要选择每个段落的上一级和下一级同级元素

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

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

selection.filter(filter)

源代码 · 过滤选择,返回一个新选择,其中只包含指定 filter 为 true 的元素。例如,要过滤一个表格行选择,使其只包含偶数行

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

这与直接使用 d3.selectAll 相当,尽管索引可能不同

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

filter 可以指定为选择器字符串或函数。如果 filter 是一个函数,则按顺序针对每个选定元素对其进行评估,并传递当前数据 (d)、当前索引 (i) 和当前组 (nodes),其中 this 为当前 DOM 元素 (nodes[i])。使用函数

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

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

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

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

返回的过滤后的选择将保留该选择的父元素,但与 array.filter 类似,它不会保留索引,因为某些元素可能会被删除;如果需要,请使用 selection.select 来保留索引。

selection.selectChild(selector)

源代码 · 返回一个新的选择,其中包含当前选择中每个元素的(第一个)子元素,这些子元素与 selector 匹配。

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

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

警告

selection.selectChild 将父元素的数据传播到选定的子元素。

selection.selectChildren(selector)

源代码 · 返回一个新的选择,其中包含当前选择中每个元素的子元素,这些子元素与选择器匹配。如果未指定选择器,则选择所有子元素。如果选择器被指定为字符串,则选择匹配的子元素(如果有)。如果选择器是一个函数,它将按顺序为每个子节点执行,并传递子元素 (child)、子元素的索引 (i) 以及子元素列表 (children);该方法将选择所有返回真值的子元素。

selection.selection()

源代码 · 返回选择(与 transition.selection 对称)。

matcher(selector)

源代码 · 给定指定的选择器,返回一个函数,如果this元素 匹配 指定的选择器,则该函数返回 true。此方法在内部由 selection.filter 使用。例如,以下代码

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

等效于

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

(虽然 D3 不是兼容层,但此实现由于element.matches 的最新标准化而支持供应商前缀实现。)

selector(selector)

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

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

等效于

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

selectorAll(selector)

源代码 · 给定指定的选择器,返回一个函数,该函数返回this元素的所有匹配指定选择器的后代。此方法在内部由 selection.selectAll 使用。例如,以下代码

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

等效于

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

window(node)

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

style(node, name)

源代码 · 返回指定node 的指定name 的样式属性的值。如果node 有一个具有指定name 的内联样式,则返回其值;否则返回 计算后的属性值。另请参阅 selection.style