2015-09-25 39 views
1

我创建了一个在D3的selection.each()中调用的转换,但回调和转换之间存在一个小的延迟。我想过渡似乎是连续,而不是有轻微的延迟。我尝试过不同的持续时间和延迟值,但无济于事。这是相关的代码。在每个()回调(D3)中触发的平滑过渡

transition(); 

function transition() { 

    data.map((d) => { 
     d.x = d3.random.normal(d['x'], 5)(); 
     d.y = d3.random.normal(d['y'], 5)(); 
     return d; 
    }); 

    g.selectAll('path') 
     .data(data) 
     .transition() 
     .duration(400) 
     .attr('d', (d, i) => line(getPath(d, i))) 
     .each('end', transition); 

} 

正如你可以看到this working codepen,还有就是转换之间轻微的延迟。我希望过渡看起来是连续的。我怎样才能做到这一点?

回答

1

几个百分点......

  1. 默认在D3过渡缓和不是线性的,这样就是为什么你察觉的延迟。
  2. 在每个单独的路径转换完成后,您实际上正在设置新的转换。 each方法回调选择中的每个节点,并且在d3转换中没有内置的endall事件,但you can make one如下所示。

第一点可能是最重要的。第二点是避免不必要地重新应用转换并中断以前应用的转换。无论如何,这可能不是可以察觉的,但是不错的做法。

这里是工作的例子...

var colors = [ 
 
\t '#FFAA5C', 
 
\t '#DA727E', 
 
\t '#AC6C82', 
 
\t '#685C79', 
 
\t '#455C7B' 
 
] 
 

 

 

 
var line = d3.svg.line() 
 
\t .x((d) => d.x) 
 
\t .y((d) => d.y) 
 
\t .interpolate('linear'); 
 

 
var svg = d3.select('body').append('svg'); 
 

 
var svgW = d3.select('svg').node().clientWidth; 
 
var svgH = d3.select('svg').node().clientHeight; 
 

 
var w = svgW/4; 
 
var h = svgH/4; 
 

 
var data = [ \t {x: -w/2, y: -h/4}, {x: 0, y: -h/2}, {x: w/2, y: -h/4}, 
 
\t \t \t \t \t \t \t \t {x: w/Math.PI, y:h/2.5}, {x: -w/4, y: h/2.5} ]; 
 

 
var getPath = (d, i) => { 
 
\t var path = []; 
 
\t 
 
\t var startPoint = { x: 0, y: 0 }; 
 
\t // point 1 
 
\t path.push(startPoint); 
 

 
\t // point 2 
 
\t path.push(d); 
 
\t 
 
\t // point 3 
 
\t path.push(data[i + 1] || data[0]); 
 
\t 
 
\t // point 4 
 
\t path.push(startPoint); 
 
\t 
 
\t return path; 
 

 
} 
 

 
var g = svg.append('g') 
 
\t .attr('transform', 'translate(' + svgW/2 + ',' + svgH/2 + ')'); 
 

 
g.selectAll('path') 
 
\t .data(data) 
 
.enter().append('path') 
 
\t .attr({ 
 
\t \t fill: (d, i) => colors[i] 
 
\t }); 
 

 
transition(); 
 

 
function transition() { 
 
\t 
 
\t data.map((d) => { 
 
\t \t d.x = d3.random.normal(d['x'], 5)(); 
 
\t \t d.y = d3.random.normal(d['y'], 5)(); 
 
\t \t return d; 
 
\t }); 
 
\t 
 
\t g.selectAll('path') 
 
\t \t .data(data) 
 
\t \t .transition() 
 
\t \t .ease("linear") 
 
\t \t .duration(50) 
 
\t \t .attr('d', (d, i) => line(getPath(d, i))) 
 
\t \t .call(endall, function(){window.requestAnimationFrame(transition)}); 
 
\t 
 
} 
 

 
    function endall(transition, callback) { 
 
    if (transition.size() === 0) { callback() } 
 
    var n = 0; 
 
    transition 
 
     .each(function() { ++n; }) 
 
     .each("end", function() { if (!--n) callback.apply(this, arguments); }); 
 
    }
body { 
 
\t background-color: #181818; 
 
\t display: flex; 
 
\t justify-content: center; 
 
\t align-items: center; 
 
\t height: 100vh; 
 
\t width: 100%; 
 
} 
 

 
svg { 
 
\t overflow: visible; 
 
\t width: 100%; 
 
\t height: 100%; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

+0

有趣的实现。另外,我完全认为线性是默认的缓动功能。感谢您深思熟虑的回应。 – Himmel

+0

干杯@Himmel我的灵感来自于演示的设计。太好了! –