转换链接和取消



我有两个函数在行上执行动画。第一个函数one在开始时执行,以执行对enter选择的操作,并且只显示线条的水平移动(x1x2)。第二个函数two只动画线的高度(只有y2, y1保持固定)。

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

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

http://jsfiddle.net/h39WN/6/-请做以下操作:点击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){ ... });

http://jsfiddle.net/96uN6/8/这是包含此更改的文件。即使twoone打断,正确的高度结果在结束- but:

y2现在也在one中动画了!我知道.transition()的默认持续时间为250ms,所以我这样做:

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){ ... });

在常规选择中设置y2而不是过渡选择也不起作用,因为它带来了"干扰"问题-因为当two的动画仍在运行时设置y2

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 (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/

最新更新