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)
?或者,换言之,为什么这有时有效,有时无效?不确定这是否是解决您问题的正确解决方案,但您可以在功能“一”运行时禁用按钮“二”。下面是一个例子——这是一个很好的解决方案,但如果用户在“一”动画完成之前单击“二”,仍然会出现混乱的线条。当然,当两个用例都可能出现时,您需要以相同的方式修改代码。