过渡链接和取消

时间:2014-05-16 13:07:22

标签: animation d3.js transition

我有两个在线上执行动画的功能。第一个函数one在开头执行,以便对输入选择执行操作,并且仅动画线条'水平移动(x1x2)。第二个函数two仅动画线条'高度(仅y2y1保持不变)。

通过用户事件,函数one不能被函数two中断,反之亦然(因为two中的动画要长得多)。这意味着,当two的转换仍在运行时,用户可以触发one

这给了我严重的麻烦,因为one会以某种方式获取two正在运行的转换的最后状态的值,而不是正确地分配数据驱动的值(即.attr('y2', function(d){ ... }); )。

http://jsfiddle.net/h39WN/6/ - 请执行以下操作:点击one。您会看到只有水平移动在数据更改时才会生成动画。您还会看到,在执行结束时,应始终从最低到最高排序。 单击two一次,等待整整2秒,直到动画完成。然后再次点击one。这是理想的行为。

现在点击two,等待几毫秒,然后点击one - 您会看到这些行保持two动画的最后状态的高度,即使它们是正确的订购。 (我知道数据不现实,在这个例子中可能有点令人困惑,但它们仍然允许复制问题)。

然后我想出了一个解决方案来安排另一个"空的",转换到one中的行 - 根据文档,这应该取消仍然在{{1}中运行的那个调用two时:

one

这是第二个功能。

var one = function () {

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

    vis.mobileTeams = svg
        .selectAll('.teamGroup')
        .data(data.values, function (d) {
            return d.ID;
        });

    // ENTER
    var teamEnter = vis.mobileTeams
        .enter()
        .append('g')
        .attr('class', 'teamGroup');
    // enter line
    teamEnter
        .append('line')
        .attr('class', 'teamWeightedLine');


    // UPDATE THE LINE
    // HEIGHT - SHOULD NOT BE ANIMATED
    svg
        .selectAll('.teamGroup line')
        .attr('y1', paddingY)

    // I inserted a transition here to cancel 
    // the one triggered by the other function
    var lineTransition = svg
        .selectAll('.teamGroup line')
        .transition()
        .attr('y2', function(d){ ... });

    // I need to use transition chaining so changing 'y2' 
    // with a transition does not get 
    // overwritten by the following transition

    // HORIZONTAL POSITION - SHOULD BE ANIMATED
    lineTransition
        .transition()
        .duration(500)
    // 'x1' and 'x2' are the only values that 
    // need to be animated in this function
        .attr('x1', function (d) {
            return function(d){ ... });
        })
        .attr('x2', function (d) {
            return function(d){ ... });
        });
};

尽管这可以解决"干扰问题。问题因为var two = function () { var svg = d3.select('svg'); // this is where the only transition concerning HEIGHT is supposed to take place svg .selectAll('.teamGroup line') .transition() .ease('circle-out') .duration(2000) .attr('y2', vis.mobileCalculateScoreToHeight); console.log('mobile vis updated'); }; 的过渡被取消,因为另一个被安排,它带来了另一个问题:

two

http://jsfiddle.net/96uN6/8/这是包含这种变化的小提琴。即使var lineTransition = svg .selectAll('.teamGroup line') .transition() .attr('y2', function(d){ ... }); two打断,也会在最后产生正确的高度 - 但是:

one现在也在y2中动画了!我知道one带来的默认持续时间为250毫秒,所以我这样做了:

.transition()

这又带来了另一个问题:var lineTransition = svg .selectAll('.teamGroup line') .transition() .duration(0) .attr('y2', function(d){ ... }); 现在根本没有设置,即y2甚至没有将其作为属性:

奇怪的是,它在使用非常短的持续时间时起作用(因此动画几乎看不到),但它只在某些情况下有效并且可能依赖于浏览器:

<line>

在常规选择中设置var lineTransition = svg .selectAll('.teamGroup line') .transition() .duration(10) .attr('y2', function(d){ ... }); 而不是转换选择也不起作用,因为它会带来&#34;干扰&#34;问题 - 当y2的动画仍在运行时设置为y2

two

当然,没有转换链接的方法也不起作用,因为第一个转换立即被第二个转换取消,svg .selectAll('.teamGroup line') .attr('y1', paddingY) .attr('y2', function(d){ ... }); var lineTransition = svg .selectAll('.teamGroup line') .transition(); 从未设置。

y2

因此,唯一可能为我工作的解决方案(持续时间短的解决方案)似乎非常古怪,必须有更好的解决方案,不是吗? 如果有什么不清楚,请随时询问。

1 个答案:

答案 0 :(得分:1)

通过Mike Bostock(https://github.com/mbostock/d3/issues/1877),我发现我可以使用selection.interrupt()取消任何先前的转换,即已经运行的转换。

所以,古怪的

var lineTransition = svg
            .selectAll('.teamGroup line')
            .transition()
            .duration(0)
            .attr('y2', function(d){ ... });

变为

var lineTransition = svg
            .selectAll('.teamGroup line')
            .interrupt()
            .attr('y2', function(d){ ... });

就这么简单。

请参阅:http://jsfiddle.net/96uN6/9/