跳到內容

選取元素

選取是 DOM 中的一組元素。通常這些元素會透過 選擇器 識別,例如 .fancy 代表具有 fancy 類別的元素,或 div 選取 DIV 元素。

選取方法有兩種形式,selectselectAll:前者只選取第一個符合條件的元素,而後者選取文件順序中所有符合條件的元素。頂層選取方法 d3.selectd3.selectAll 會查詢整個文件;子選取方法 selection.selectselection.selectAll 會將選取範圍限制在選取元素的後代元素。另外還有 selection.selectChildselection.selectChildren,用於選取直接子元素。

依慣例,會回傳目前選取範圍的選取方法,例如 selection.attr,會使用四個空格縮排,而會回傳新的選取範圍的方法只使用兩個空格縮排。這有助於透過讓它們從鏈中凸顯出來,來揭示內容的變更

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 為 null 或未定義,則傳回一個空的選取。

如果 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>

如果沒有元素符合目前元素指定的 selector,則傳回選取中目前索引的元素會為 null。(如果 selector 為 null,則傳回選取中的每個元素都會為 null,導致一個空的選取。)如果目前元素有相關聯的資料,這個資料會傳播到對應的選取元素。如果有多個元素符合 selector,則只會選取文件順序中的第一個符合元素。

如果 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 相符,或如果 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)");

篩選器 可以指定為選擇器字串或函式。如果 篩選器 是函式,則會依序對每個選取的元素進行評估,傳遞目前的資料 (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 偽類別是一個以 1 為基礎的索引,而不是以 0 為基礎的索引。此外,上述篩選器函式與 :nth-child 的意義並不完全相同;它們依賴於選擇器索引,而不是 DOM 中前面同層元素的數量。

回傳的篩選選擇會保留此選擇的父層,但與 array.filter 類似,它不會保留索引,因為某些元素可能會被移除;如果需要,請使用 selection.select 來保留索引。

selection.selectChild(selector)

來源 · 回傳一個新的選擇,其中包含目前的選擇中每個元素的 (第一個) 子元素,這些子元素符合 selector

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

如果未指定 selector,則選擇第一個子元素 (如果有)。如果 selector 指定為字串,則選擇符合的第一個子元素 (如果有)。如果 selector 是函式,則會依序對每個子節點進行評估,傳遞子元素 (child)、子元素的索引 (i) 和子元素清單 (children);如果選擇器回傳真值,則此方法會選擇第一個子元素 (如果有)。

注意

selection.selectChild 將父層的資料傳播到選取的子元素。

selection.selectChildren(selector)

原始碼 · 傳回一個新的選取,其中包含與selector 相符的目前選取中每個元素的子元素。如果未指定selector,則選取所有子元素。如果selector 指定為字串,則選取相符的子元素(如果有)。如果selector 為函式,則會依序對每個子元素節點評估,傳遞子元素(child)、子元素的索引(i)和子元素清單(children);此方法會選取 selector 傳回真值的每個子元素。

selection.selection()

原始碼 · 傳回選取(與 transition.selection 對稱)。

matcher(selector)

原始碼 · 根據指定的selector,傳回一個函式,如果this 元素 符合 指定的 selector,則傳回 true。此方法由 selection.filter 內部使用。例如,這是

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

等於

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

(儘管 D3 不是相容性層,但由於element.matches 近期標準化,此實作支援供應商前綴實作。)

selector(selector)

原始碼 · 根據指定的selector,傳回一個函式,傳回與指定 selector 相符的this 元素的第一個後代。此方法由 selection.select 內部使用。例如,這是

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

等於

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

selectorAll(selector)

原始碼 · 根據指定的selector,傳回一個函式,傳回與指定 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