我有两个在线上执行动画的功能。第一个函数one
在开头执行,以便对输入选择执行操作,并且仅动画线条'水平移动(x1
和x2
)。第二个函数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
中的行 - 根据文档,这应该取消仍然在{{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
因此,唯一可能为我工作的解决方案(持续时间短的解决方案)似乎非常古怪,必须有更好的解决方案,不是吗? 如果有什么不清楚,请随时询问。
答案 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){ ... });
就这么简单。