javascript - D3.enter().merge() 不起作用

标签 javascript d3.js

我正在努力让 V4 中的常规更新模式发挥作用,尽管我相信我通过 merge() 了解了它的新工作原理。我遇到奇怪的结果。这是我的更新功能:

function update(data) {

    //I create and empty selection, and use the key function with an ID string
    //in my dsv data.
    var bubs = dataLr.selectAll(".data-bub")
        .data(data, function(d) {
            return d.id || (d.id = ++i);
        });

    //remove any that dont need to be there.
    //The first time around there wont be any nodes in the exit, but no matter.
    bubs.exit()
        .transition(tIntro)
        .style("opacity", 0)
        .each(function(d) {
            //Log out the removed elements.
            console.log(d.id);
        })
        .remove();

    bubs.enter() //add any new ones - a group and a circle within it.
        .append("g")
        .classed("data-bub", true)
        .on("click", function(d) {
            console.log(d);
        })
        .append("circle")
        .attr("r", 20)
        .classed("bub", true)
        .merge(bubs);//here I merge the enter with the update.


    //Now I should be able to run this transition that 
    //moves each group to a random location on my svg.
    //But nothing happens. Why is the update selection empty after merge?
    bubs.transition(tIntro)
        .attr("transform", function(d, i) {
            ///console.log(i);
            var y = Math.random() * gHeight;
            var x = Math.random() * gWidth;
            return "translate(" + x + "," + y + ")";
        });

}

此外,另一件奇怪的事情不断发生。目前我正在运行此函数而不更改数据。因此,不应在 exit()enter() 上删除任何元素。然而每次都会删除并重新添加两个随机的?什么鬼?

最佳答案

.merge() 不会更改选择 - 在 d3v4 中选择是不可变的。因此,一旦声明,选择将始终保持不变,除非您重新定义它。如果您的初始 selectAll 方法返回空选择,则 bubs 在更新选择中不会有任何内容 - 直到您重新定义 bubs。所有合并所做的是:

Returns a new selection merging this selection with the specified other selection. (docs)

如果您只是附加 g 元素,那么您可以使用:

bubs.enter() 
    .append("g")
    .merge(bubs)
    // apply transition to enter and update selection
    .transition()...

或者,使用合并返回的选择重新定义 bubs:

bubs = bubs.enter() 
    .append("g")
    .merge(bubs);

// apply transition to enter and update selection
bubs.transition()....

但是您的代码会遇到问题,因为您有两种不同类型元素的两个选择:selectAll(".data-bub") 的初始选择 - 选择 g 元素基于您的代码,以及选择的输入圆圈:

bubs.enter()         
    .append("g")               // return entered g elements
    .classed("data-bub", true) // return entered g elements with class data-bub
    .append("circle")          // return entered circles
    .merge(bubs);              // return entered circles with initially selected g elements

如果您将过渡应用到合并的元素,您的过渡将不均匀地应用 - 在更新的情况下应用到父 g 元素,而应用到子 circle 元素在进入的情况下。这可能会导致不良结果(例如,如果您还有子文本元素)。要解决此问题(并对输入和更新的 g 元素应用转换),您可以尝试以下操作:

    var bubs = dataLr.selectAll(".data-bub")
        .data(data, function(d) { return d.id || (d.id = ++i); });

    // remove as before
    bubs.exit()
       .remove();

   // enter new groups
   var enter = bubs.enter()  
      .append("g")
      .classed("data-bub", true);

   // append circles to the new groups
   enter.append("circle")
        .attr("r", 20)
        .classed("bub", true)

   // merge enter and update, apply transition
   enter.merge(bubs)
      .transition()....

关于javascript - D3.enter().merge() 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47802266/

相关文章:

javascript - html5 本地存储是否按 iframe 存储?

javascript - Mapbox如何隐藏一些兴趣点

javascript - 工具提示/悬停中的音频?

javascript - d3.js voronoi 事件。当光标正好位于点上方时,鼠标悬停似乎消失

javascript - 如何在 D3.JS 或 moment 中解析像 '2009-09-13' 这样的日期

javascript - 打破 promise 链

javascript - 谷歌图表 : How to auto re-size inside panel?

d3.js - 找到 topoJSON 路径的质心并用它在 D3 中定位一个圆

javascript - 使用相对的 SVG 宽度和高度在中心节点周围均匀分布节点

javascript - 如何在 D3.js 中添加箭头链接?