簡體   English   中英

事件處理程序中的d3選擇:select vs selectAll

[英]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控制台。

  1. 無法按預期工作: http : //jsfiddle.net/bdy8z7dh/1/
    • 在這里,我將代碼移到了最小的“可重用圖表”函數中。
    • 該版本無法按預期運行:在第一次單擊事件上可以運行,但是在下一個事件中未定義node_id(請參見JS控制台)。
    • 請注意,我將“父”元素保存在變量中, d3.select在事件回調中使用全局d3.select
  2. 再次按預期工作: http : //jsfiddle.net/bdy8z7dh/2/
    • 在這里,我只是將parent.select更改為parent.selectAll ,現在示例再次按預期工作。

另一個解決方法是使用全局d3.select而不是parent.select 但是有些事情我還不了解:為什么第二小提琴不起作用? 我想念什么? 它可能與JS中的作用域有關,因為第一個最小示例起作用了?

PS。 我的意圖是將所有三個代碼片段都放在小提琴中,但是我的代表太低而無法發布多個鏈接。 我也想鏈接到Mike Bostock關於可重用圖表的文章,但是現在您可以通過搜索“指向可重用圖表”來找到它。

@LarsKotthoff在他的評論中完全正確。

您正在使用正確的數據初始化元素,因此第一個開關運行良好。 但是,當您從第一個選定的按鈕切換開時, parent.select調用會將選定按鈕上的數據更改為最初僅在父級上的整個數據數組。 但是, parent.selectAll不會傳播父數據,因此在這種情況下就可以了。

為了驗證這一點,我在示例中的第19行添加了另一個控制台輸出:

相關文檔部分位於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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM