在.each()回调中触发平滑过渡(D3)

时间:2015-09-25 19:45:09

标签: javascript d3.js

我创建了一个在D3 selection.each()中调用的转换,但回调和转换之间有一点延迟。我希望过渡似乎是连续而不是稍微延迟。我试过玩不同的持续时间和延迟值但无济于事。这是相关的代码。

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 个答案:

答案 0 :(得分:1)

有几点......

  1. d3过渡中的默认缓动不是线性的,这就是您感知延迟的原因。
  2. 您实际上是在每个单独的路径转换完成后设置新的转换。 var colors = [ '#FFAA5C', '#DA727E', '#AC6C82', '#685C79', '#455C7B' ] var line = d3.svg.line() .x( (d) => d.x ) .y( (d) => d.y ) .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 = [ {x: -w/2, y: -h/4}, {x: 0, y: -h/2}, {x: w/2, y: -h/4}, {x: w/Math.PI, y:h/2.5}, {x: -w/4, y: h/2.5} ]; var getPath = (d, i) => { var path = []; var startPoint = { x: 0, y: 0 }; // point 1 path.push(startPoint); // point 2 path.push(d); // point 3 path.push(data[i + 1] || data[0]); // point 4 path.push(startPoint); return path; } var g = svg.append('g') .attr('transform', 'translate(' + svgW/2 + ',' + svgH/2 + ')'); g.selectAll('path') .data(data) .enter().append('path') .attr({ fill: (d, i) => colors[i] }); 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() .ease("linear") .duration(50) .attr('d', (d, i) => line( getPath(d, i) ) ) .call(endall, function(){window.requestAnimationFrame(transition)}); } 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); }); }方法回调选择中的每个节点,并且d3过渡中没有内置的endall事件,但you can make one如下所示。
  3. 第一点可能是最重要的。第二点是避免不必要地重新应用转换并中断先前应用的转换。无论如何,可能不是可察觉但是很好的练习。

    这是一个有效的例子......

    
    
    body {
    	background-color: #181818;
    	display: flex;
    	justify-content: center;
    	align-items: center;
    	height: 100vh;
    	width: 100%;
    }
    
    svg {
    	overflow: visible;
    	width: 100%;
    	height: 100%;
    }
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
    &#13;
    protected void gvHead_OnRowDataBound(object sender, GridViewRowEventArgs e) {
      for (int i = 0; i < e.Row.Cells.Count; i++) 
        e.Row.Cells[i].Text = HttpUtility.HtmlDecode(e.Row.Cells[i].Text);
    }
    
    &#13;
    &#13;
    &#13;