Animation 过渡链接和取消

Animation 过渡链接和取消,animation,d3.js,transition,Animation,D3.js,Transition,我有两个函数可以在线条上执行动画。第一个函数,one在开始时执行,以便对enter选择执行操作,并且仅为行的水平移动设置动画(x1和x2)。第二个函数two仅设置线条高度的动画(仅y2,y1保持固定) 通过用户事件,函数one不能被函数two中断,反之亦然(这也是因为two中的动画要长得多)。这意味着,当从two的转换仍在运行时,用户可以触发one 这让我非常头疼,因为one会以某种方式获取two运行转换的最后状态的值,而不是正确分配数据驱动的值(即.attr('y2',function(d){

我有两个函数可以在线条上执行动画。第一个函数,
one
在开始时执行,以便对enter选择执行操作,并且仅为行的水平移动设置动画(
x1
x2
)。第二个函数
two
仅设置线条高度的动画(仅
y2
y1
保持固定)

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

这让我非常头疼,因为
one
会以某种方式获取
two运行转换的最后状态的值,而不是正确分配数据驱动的值(即
.attr('y2',function(d){…};

-请执行以下操作:单击
one
。您可以看到,随着数据的更改,只有水平移动才会设置动画。您还可以看到,在执行结束时,行的顺序应该始终是从最低到最高。 单击
two
一次,等待整整2秒钟,直到动画完成。然后再次单击
one
。这是理想的行为

现在单击
two
,等待几毫秒,然后单击
one
——您会看到,即使顺序正确,线条仍保持
two
动画最后状态的高度。(我知道数据不现实,在本例中可能有点混乱,但它们仍然允许复制问题)

然后,我想出了一个解决方案,在
one
中的行上安排另一个“空”转换-根据文档,当调用
one
时,这将取消仍在
two
中运行的转换:

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
的转换因另一个转换被取消,但它带来了另一个问题:

var lineTransition = svg
            .selectAll('.teamGroup line')
            .transition()
            .attr('y2', function(d){ ... });
这就是包含这一变化的小提琴。即使当
two
one
中断时,正确的高度是否会导致结束-但是:

y2
现在也正在
one
中设置动画!我知道
.transition()
附带了250毫秒的默认持续时间,所以我这样做了:

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

奇怪的是,它在使用非常短的持续时间时工作(因此动画几乎不可见),但它只在某些时候工作,并且可能依赖于浏览器:

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

svg
    .selectAll('.teamGroup line')
    .attr('y1', paddingY)
    .attr('y2', function(d){ ... });

var lineTransition = svg
    .selectAll('.teamGroup line')
    .transition();
当然,没有转换链接的方法也不起作用,因为第一个转换会立即被第二个转换取消,并且不会设置
y2

svg
        .selectAll('.teamGroup line')
        .transition()
        .duration(10)
        .attr('y2', function(d){ ... });

    svg
        .selectAll('.teamGroup line')
        .transition()
        .duration(TRANSDURATION)
        .attr('x1', function (d) {
            return function(d){ ... };
        })
        .attr('x2', function (d) {
            return function(d){ ... };
        });
所以对我来说唯一可行的解决方案(持续时间短的那个)似乎很奇怪,一定有更好的解决方案,不是吗? 请随意询问是否有不清楚的地方。

通过Mike Bostock(),我发现我可以使用
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){ ... });
就这么简单


请参阅:

我在这方面遇到了一些困难--你能举个小例子来说明问题吗?@LarsKotthoff我添加了小提琴,希望能解释发生了什么-这很难,因为我无法使用应用程序的现有基础结构,即真实数据,但无论如何,欢迎提出更多问题。感谢您的澄清。这种行为在很大程度上是设计的,我认为在当前版本的D3中没有一种很好的方法来做你想做的事情——理想情况下,你需要一个“中断”的转换事件(这可能并不难实现,但需要修改源代码)。在您的应用程序中,是否可以将两个转换合并到一个函数中以消除此问题,例如(只需单击“一”)?不,我需要这两个函数,因为用户设置值时会触发后一个函数,即根据用户指定的值缩放数据,并使用可拖动的句柄,而第二个是在按下按钮时调用的,该按钮由一个
处理-两个不同的操作,两个不同的数据操作。嗯。但是为什么我不能设置
.duration(0)
?或者,换言之,为什么这有时有效,有时无效?不确定这是否是解决您问题的正确解决方案,但您可以在功能“一”运行时禁用按钮“二”。下面是一个例子——这是一个很好的解决方案,但如果用户在“一”动画完成之前单击“二”,仍然会出现混乱的线条。当然,当两个用例都可能出现时,您需要以相同的方式修改代码。