選取元素
選取是 DOM 中的一組元素。通常這些元素會透過 選擇器 識別,例如 .fancy
代表具有 fancy 類別的元素,或 div
選取 DIV 元素。
選取方法有兩種形式,select 和 selectAll:前者只選取第一個符合條件的元素,而後者選取文件順序中所有符合條件的元素。頂層選取方法 d3.select 和 d3.selectAll 會查詢整個文件;子選取方法 selection.select 和 selection.selectAll 會將選取範圍限制在選取元素的後代元素。另外還有 selection.selectChild 和 selection.selectChildren,用於選取直接子元素。
依慣例,會回傳目前選取範圍的選取方法,例如 selection.attr,會使用四個空格縮排,而會回傳新的選取範圍的方法只使用兩個空格縮排。這有助於透過讓它們從鏈中凸顯出來,來揭示內容的變更
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
。
const root = d3.selection();
此函式也可以用來測試選取(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);
select(selector)
原始碼 · 選取符合指定 selector 字串的第一個元素。
const svg = d3.select("#chart");
如果沒有元素符合 selector,則傳回一個空的選取。如果有多個元素符合 selector,則只會選取第一個符合的元素(依據文件順序)。例如,選取第一個錨點元素
const anchor = d3.select("a");
如果 selector 不是字串,則會選取指定的節點;這在已經有節點的參考時很有用,例如 document.body
。
d3.select(document.body).style("background", "red");
或者,讓被按下的段落變紅
d3.selectAll("p").on("click", (event) => d3.select(event.currentTarget).style("color", "red"));
selectAll(selector)
原始碼 · 選取符合指定 selector 字串的所有元素。
const p = d3.selectAll("p");
元素將會依據文件順序(由上到下)選取。如果文件中的元素沒有符合 selector,或者 selector 為 null 或未定義,則傳回一個空的選取。
如果 selector 不是字串,則會選取指定的節點陣列;這在已經有節點的參考時很有用,例如事件監聽器中的 this.childNodes
或全域變數 document.links
。節點也可以是可迭代的,或類陣列,例如 NodeList。例如,讓所有連結變紅
d3.selectAll(document.links).style("color", "red");
selection.select(selector)
原始碼 · 對於每個選取的元素,選取第一個符合指定 selector 字串的後代元素。
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。例如,選取每個段落的先前同層元素
const previous = d3.selectAll("p").select(function() {
return this.previousElementSibling;
});
與 selection.selectAll 不同,selection.select 不會影響群組:它會保留現有的群組結構和索引,並將資料(如果有)傳播到選取的子項。群組在 資料合併 中扮演重要的角色。請參閱 巢狀選取 和 選取如何運作 以深入了解這個主題。
注意
selection.select 會將父項的資料傳播到選取的子項。
selection.selectAll(selector)
原始碼 · 針對每個選取的元素,選取與指定的 selector 字串相符的後代元素。
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),或在沒有相符元素時傳回空的陣列。例如,若要選取每個段落的先前和下一個同層元素
const sibling = d3.selectAll("p").selectAll(function() {
return [
this.previousElementSibling,
this.nextElementSibling
];
});
與 selection.select 不同,selection.selectAll 會影響群組:每個選取的後代都會按原始選取中的父元素進行分組。群組在 資料合併 中扮演重要的角色。請參閱 巢狀選取 和 選取如何運作 以深入了解這個主題。
selection.filter(filter)
原始碼 · 過濾選取,傳回新的選取,其中只包含指定的 filter 為 true 的元素。例如,若要過濾表格列的選取,只包含偶數列
const even = d3.selectAll("tr").filter(":nth-child(even)");
這大約等於直接使用 d3.selectAll,儘管索引可能不同
const even = d3.selectAll("tr:nth-child(even)");
篩選器 可以指定為選擇器字串或函式。如果 篩選器 是函式,則會依序對每個選取的元素進行評估,傳遞目前的資料 (d)、目前的索引 (i) 和目前的群組 (nodes),其中 this 為目前的 DOM 元素 (nodes[i])。使用函式
const even = d3.selectAll("tr").filter((d, i) => i & 1);
或使用 selection.select (並避免使用箭頭函式,因為需要 this 來參考目前的元素)
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。
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 內部使用。例如,這是
const div = selection.filter("div");
等於
const div = selection.filter(d3.matcher("div"));
(儘管 D3 不是相容性層,但由於element.matches 近期標準化,此實作支援供應商前綴實作。)
selector(selector)
原始碼 · 根據指定的selector,傳回一個函式,傳回與指定 selector 相符的this
元素的第一個後代。此方法由 selection.select 內部使用。例如,這是
const div = selection.select("div");
等於
const div = selection.select(d3.selector("div"));
selectorAll(selector)
原始碼 · 根據指定的selector,傳回一個函式,傳回與指定 selector 相符的this
元素的所有後代。此方法由 selection.selectAll 內部使用。例如,這是
const div = selection.selectAll("div");
等於
const div = selection.selectAll(d3.selectorAll("div"));
window(node)
原始碼 · 傳回指定 node 的擁有者視窗。如果 node 是節點,則傳回擁有者文件預設的檢視;如果 node 是文件,則傳回其預設的檢視;否則傳回 node。
style(node, name)
原始碼 · 傳回指定 node 中具有指定 name 的樣式屬性的值。如果 node 具有具有指定 name 的內嵌樣式,則傳回其值;否則,傳回 計算出的屬性值。另請參閱 selection.style。