2016-02-23 45 views
1

对于一系列元素(在本例中为三行),我无法获得重复转换。动画只运行一次,但是当它重复(使用相同的数据)时,所有三行合并成一行(data中的最后一个数组)。我究竟做错了什么?d3:系列元素的重复过渡?

(function() { 
 
    var w = 100, h = 100 
 
    var div = d3.select('#sketches').append('div') 
 
    var svg = div.append("svg") 
 
     .attr("width", w) 
 
     .attr("height", h) 
 

 
    var x = 0, y = 55 
 

 
    var data = [ 
 
     [x, y, x+20, y-40], 
 
     [x+10, y, x+30, y-40], 
 
     [x+20, y, x+40, y-40] 
 
    ]; 
 

 
    (function lines() { 
 
      svg.selectAll('line') 
 
       .data(data).enter().append('line') 
 
       .attr("stroke", "black") 
 
       .attr('x1', function(d) {return d[0]}) 
 
       .attr('y1', function(d) {return d[1]}) 
 
       .attr('x2', function(d) {return d[2]}) 
 
       .attr('y2', function(d) {return d[3]}) 
 
       .transition() 
 
       .duration(3000) 
 
       .ease('linear') 
 
       .attr('x1', function(d) {return d[0] + 60}) 
 
       .attr('y1', function(d) {return d[1]}) 
 
       .attr('x2', function(d) {return d[2] + 60}) 
 
       .attr('y2', function(d) {return d[3]}) 
 
       .each('end', function(d) { 
 
        d3.select(this).remove() 
 
        lines() 
 
       }) 
 
    })() 
 
})()
body { 
 
    padding: 1rem; 
 
} 
 
svg { 
 
    background-color: silver; 
 
    stroke: black; 
 
    stroke-width: 1; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> 
 

 
<div id="sketches"></div>

回答

1

的问题是each功能将开始对你有每一行。所以实际上你每次打电话lines()三次。为什么它是一条线的输出我不完全确定(仍在研究它),但由于某种原因,data默认为最后一个数组,因此它只能根据data[3]设置绘图。

要解决这个问题,您需要确保lines()只有在删除所有行后才会调用,因此只能运行一次。我很肯定有更好的方法(即承诺某种形式,所以each已经运行,它会运行一个函数,但你可以做的是设置一个count,然后运行lines()每N次,其中N是你想要删除的行数,因为你要经过数组data并为每个索引添加一行,N是data.length

(我要去看看是否有更干净的方法来做到这一点,我会编辑我的答案,如果我找到一个方法,但希望这可以帮助你了解这个问题至少是)

(function() { 
 
    var w = 100, h = 100 
 
    var div = d3.select('#sketches').append('div') 
 
    var svg = div.append("svg") 
 
     .attr("width", w) 
 
     .attr("height", h) 
 

 
    var x = 0, y = 55 
 

 
    var data = [ 
 
     [x, y, x+20, y-40], 
 
     [x+10, y, x+30, y-40], 
 
     [x+20, y, x+40, y-40] 
 
    ]; 
 
    
 
    var count = 0; 
 
    (function lines() { 
 
      svg.selectAll('line') 
 
       .data(data).enter().append('line') 
 
       .attr("stroke", "black") 
 
       .attr('x1', function(d) {return d[0]}) 
 
       .attr('y1', function(d) {return d[1]}) 
 
       .attr('x2', function(d) {return d[2]}) 
 
       .attr('y2', function(d) {return d[3]}) 
 
       .transition() 
 
       .duration(3000) 
 
       .ease('linear') 
 
       .attr('x1', function(d) {return d[0] + 60}) 
 
       .attr('y1', function(d) {return d[1]}) 
 
       .attr('x2', function(d) {return d[2] + 60}) 
 
       .attr('y2', function(d) {return d[3]}) 
 
       .each('end', function(d) { 
 
        d3.select(this).remove() 
 
        count++; 
 
        if (count == data.length) { 
 
         count = 0; 
 
         lines(); 
 
        } 
 
       }) 
 
    })() 
 
})()
body { 
 
    padding: 1rem; 
 
} 
 
svg { 
 
    background-color: silver; 
 
    stroke: black; 
 
    stroke-width: 1; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> 
 

 
<div id="sketches"></div>

+0

谢谢,这解决了它,现在'each()'调用问题似乎很明显。另外,既然你已经给了我正确的条款给谷歌,我看到至少有一个其他用户corroborates你的方法:http://stackoverflow.com/a/23119420/652626 – allanberry

+1

@niteshade是更多的调查后,我发现这是Mike Bostock推荐的做法。看[这个答案](http://stackoverflow.com/a/20773846/1168661) – aug