我有两个函数在行上执行动画。第一个函数one
在开始时执行,以执行对enter选择的操作,并且只显示线条的水平移动(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
的行上安排另一个"空"过渡-根据文档,当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/这是包含此更改的文件。即使two
被one
打断,正确的高度结果在结束- 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/