D3.js D3转换--exit()选择的转换失败

D3.js D3转换--exit()选择的转换失败,d3.js,transitions,D3.js,Transitions,我有一个非常简单的D3用例: var dat = [0,1,2,3,4,5]; var svg = d3.select("#main"); svg.selectAll("div.box").data(dat).enter().append("div").attr("class","box").text(function(d,i){return d}); var button = d3.select("#button") button.on("mousedown",func

我有一个非常简单的D3用例:

  var dat = [0,1,2,3,4,5];

  var svg = d3.select("#main");
  svg.selectAll("div.box").data(dat).enter().append("div").attr("class","box").text(function(d,i){return d});

  var button = d3.select("#button")
  button.on("mousedown",function(){
    dat.push(dat[dat.length-1] + 1);
    dat.shift();

    var update = svg.selectAll("div.box").data(dat,function(d,i){return d});
    update.style("border-left","0px solid #0000ff").text(function(d,i){return d + ": update"});


    update.enter().append("div").attr("class","box").text(function(d,i){return d + ": enter"}).style("border-left","0px solid #00ff00");
    update.exit()
    .style("border-left","40px solid #000000")
    .text(function(d,i){
      return d + ": exit";
    }).transition().delay(5000).duration(1000)
    .style("width",function(d,i){
      //console.log(this.__transition__);
      return "0px";
    })
    .style("border-left-width","0px")
    .text("")
    .remove();

    update.transition().duration(4500).style("border-left-width","40px").each("end",function(d,i){
      d3.select(this).transition().duration(700).style("border-left-width","0px")
    })

  })
  • 用户将看到几个包含信息的框
  • 按下“更新”按钮时,新数据绑定到框集合(div),导致一个框退出,一个新框进入
  • 我想设置输入、更新和退出选择的动画
目前,我在退出选择上安排了一次延迟5秒的转换,而在合并更新选择(包括附加的enter选择)上的转换立即运行,持续时间为4.5秒

更新转换是“链接的”——我使用transition.each()在更新选择中的每个元素上安排第二次转换,并侦听“end”事件

问题:

如果用户快速单击“更新”两次或两次以上,exit()转换将无法完成,导致屏幕上的框仍然存在

我不明白为什么会发生这种情况——我不清楚现有元素上的转换是如何被覆盖的

下面是一个工作示例:

提前谢谢

JavaScript:

  var dat = [0,1,2,3,4,5];

  var svg = d3.select("#main");
  svg.selectAll("div.box").data(dat).enter().append("div").attr("class","box").text(function(d,i){return d});

  var button = d3.select("#button")
  button.on("mousedown",function(){
    dat.push(dat[dat.length-1] + 1);
    dat.shift();

    var update = svg.selectAll("div.box").data(dat,function(d,i){return d});
    update.style("border-left","0px solid #0000ff").text(function(d,i){return d + ": update"});


    update.enter().append("div").attr("class","box").text(function(d,i){return d + ": enter"}).style("border-left","0px solid #00ff00");
    update.exit()
    .style("border-left","40px solid #000000")
    .text(function(d,i){
      return d + ": exit";
    }).transition().delay(5000).duration(1000)
    .style("width",function(d,i){
      //console.log(this.__transition__);
      return "0px";
    })
    .style("border-left-width","0px")
    .text("")
    .remove();

    update.transition().duration(4500).style("border-left-width","40px").each("end",function(d,i){
      d3.select(this).transition().duration(700).style("border-left-width","0px")
    })

  })

转换存储为DOM元素属性的一部分。一旦向元素添加了新的转换,旧的转换就会丢失。您的情况是,退出选择中的元素(转换仍在运行)再次出现在更新或退出选择中,并且添加了一个新的转换,取消了旧的转换。我知道新的转换会覆盖旧的转换。在这种情况下,包含在退出选择中的元素不应该再出现在更新选择中(因为我在这里使用了键函数)。如果以前退出的元素由于处于较新的退出选择中而计划了新的转换,那么我希望较新的转换能够处理元素的删除。我很确定是“结束”事件导致了您的问题。老实说,我不知道为什么。我的理论是,第二次单击update按钮会取消活动的转换,导致“end”事件触发并应用新的转换,这会清除退出转换,因此永远不会到达.remove()调用。Ethan,我认为“end”事件导致问题的说法是对的:在初次单击时,第一个元素被添加到退出选择中,并计划了一个转换(带有延迟),最终以remove()结束。第二次单击时,第二个元素将添加到另一个退出选择中(延迟)。但由于延迟,先前运行的转换将继续运行。该转换完成,并调度其“end”事件,从而生成另一个转换。在这个过渡过程中的某个地方是延迟退出转换应该开始的时候。实际上,你并不需要<代码>。每个(“结束”,…)<代码>这里——简单地链接转换是等价的()。这也修复了错误,因此是的,它确实是最终事件处理程序。发生的情况是更新转换开始,然后(再次单击时)退出转换被安排(不运行),但在它有机会运行之前,它被更新转换的结束处理程序覆盖,该处理程序在上一次单击按钮时仍然存在。