[英]d3 selections in event handler: select vs selectAll
在使用D3.js在onclick-handler中按類選擇SVG元素時,我正在觀察(對我而言)意外的行為。 我將提供一個簡單的工作示例,然后提供兩個JS小提琴來說明問題。
該示例包含兩個<rect>
。 它們應該表現得像單選按鈕:單擊時,將僅選擇矩形。 如果任何其他矩形已經處於活動狀態,則將其禁用。 任何活動矩形都存儲在變量currently_active
。
testdata = [
{
unique_id: "3-2-1",
y: 10
},
{
unique_id: "2-3-1",
y: 40
}
];
var svg = d3.select("body").append("svg");
var rects = svg.selectAll(".node").data(testdata);
var currently_active = null;
rects.enter().append("rect")
.attr("x",10)
.attr("y", function(d){return d.y;})
.attr("width", 60)
.attr("height", 20)
.attr("class", function(d){return "node node-"+d.unique_id;})
.on("click", function(d){
var node_id = d.unique_id;
console.log(node_id);
if (currently_active == node_id) return;
if (currently_active) {
var thenode = svg.select(".node-"+currently_active);
thenode.style("fill", null);
currently_active = null;
}
var thenode = svg.select(".node-"+node_id);
thenode.style("fill", "#d11");
currently_active = node_id;
});
這個簡單的版本按預期工作。 注意:單擊的node_id
將登錄到JS控制台。
d3.select
在事件回調中使用全局d3.select
。 parent.select
更改為parent.selectAll
,現在示例再次按預期工作。 另一個解決方法是使用全局d3.select
而不是parent.select
。 但是有些事情我還不了解:為什么第二小提琴不起作用? 我想念什么? 它可能與JS中的作用域有關,因為第一個最小示例起作用了?
PS。 我的意圖是將所有三個代碼片段都放在小提琴中,但是我的代表太低而無法發布多個鏈接。 我也想鏈接到Mike Bostock關於可重用圖表的文章,但是現在您可以通過搜索“指向可重用圖表”來找到它。
@LarsKotthoff在他的評論中完全正確。
您正在使用正確的數據初始化元素,因此第一個開關運行良好。 但是,當您從第一個選定的按鈕切換開時, parent.select
調用會將選定按鈕上的數據更改為最初僅在父級上的整個數據數組。 但是, parent.selectAll
不會傳播父數據,因此在這種情況下就可以了。
為了驗證這一點,我在示例中的第19行添加了另一個控制台輸出:
select
: http : //jsfiddle.net/bdy8z7dh/12/ selectAll
: http : //jsfiddle.net/bdy8z7dh/14/ 相關文檔部分位於https://github.com/mbostock/d3/wiki/Selections#select ,其中介紹了selection.select()
如果當前元素具有關聯的數據,則此數據將由返回的子選擇繼承,並自動綁定到新選擇的元素。
關於selection.selectAll()
子選擇不繼承當前選擇的數據; 但是,如果將數據值指定為函數,則將使用祖先節點的數據d和組索引i調用此函數,以確定子選擇的數據綁定。
編輯:
您在下面的評論中是正確的:第一個示例有效,因為您將數據直接分配給rect
元素,因此svg
元素沒有要傳播的數據。 selection.select()
僅在父級具有數據時才覆蓋子selection.select()
上的數據。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.