2015-09-25 67 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我的靈感來自於演示的設計。太好了! –