使用JavaScript开启和关闭CSS过渡效果

3

大家好,

我遇到了一个问题,我正在使用CSS变换/过渡来动画化一个div元素的水平位置。具体来说,我正在使用...

// in CSS
myDiv {
    transition: transform 0.4s ease-in;
}

// in JavaScript, where "div" contains a reference to the div element
div.style.transform = translate3d(Npx, 0px, 0px);

我写了一行JavaScript代码,它可以实现平滑动画效果。也就是说,每次我调用这行JavaScript代码时,使用新的N值,该div都会从当前位置平滑地移动到新位置。

然而,有时候我需要先将div定位到新位置,但不带有过渡效果,然后再使用过渡效果移动它。例如:

  1. 使div瞬间跳到100像素,然后在400毫秒内过渡到200像素
  2. 稍后,将div跳转到500像素(没有过渡),然后将其过渡到600像素

换句话说,我想要能够移动一个div,并且能够控制新位置是立即应用还是带有过渡效果。

更加复杂的是,当过渡完成时,我有事件监听器触发;如果/当我移动div而没有过渡效果时,这些监听器不应触发。我还支持多个浏览器,因此必须处理所有供应商前缀。

伪代码中,我猜它看起来像这样:

  1. 删除过渡结束事件的事件监听器
  2. 将过渡属性设置为none
  3. 更改div的位置(例如,[div].style.transform = translate3d([starting position]px, 0px, 0px)
  4. 添加过渡结束事件的事件监听器
  5. 将过渡属性设置为具有过渡效果(例如,[div].style.transition:all 0.4s ease-in
  6. 更改div的位置(例如,[div].style.transform = translate3d([ending position]px, 0px, 0px)

由于所有供应商前缀都存在,因此这太混乱和复杂,不是实现此目标的最佳方法。(我甚至不确定它是否有效...)

那么,切换过渡/变换的最佳方法是什么?

[更新]

感谢Chandranshu的建议,我尝试切换包含过渡效果的类。

所以,我的伪代码看起来像这样:

  1. 删除过渡类
  2. 应用起始位置
  3. 恢复过渡类
  4. 应用结束位置

但是,如果我在单个JavaScript函数中执行所有四个步骤-它似乎会忽略步骤1-2,就好像它正在“净化”所有四个步骤的结果。

这里有一个jsfiddle演示它:http://jsfiddle.net/bUvX3/

相反,如果我执行步骤1和2,然后在短暂的延迟后执行步骤3和4(例如,使用setTimeout),它可以工作:http://jsfiddle.net/2mhcv/

所以,我想这是一个解决方案,但我真的不喜欢必须添加任意延迟,特别是当如此强调快速响应的UI时。

提前感谢!


请检查更新后的答案。您不再需要添加任意延迟。 - Chandranshu
1个回答

2
我认为您过于复杂化了这个问题。下面是我解决此问题的方法:
  1. 给您的div添加一个类,比如说movable。
  2. .movable声明所有的转换规则和转换结束回调函数。
  3. 如果您想要平稳地移动您的div,则不需要做任何事情。
  4. 当您需要在没有转换的情况下移动您的div时,请删除此类,移动您的div并重新添加此类:$('div').removeClass('movable').animate({transform: 'translate3d(...)' }).addClass('movable')
更新: 最终,我得到了您想要的: http://jsfiddle.net/2mhcv/1/。唯一的改变是,我使用了0的延迟而不是20ms的延迟!setTimeout()会触发重绘,确保第一个动画在下一个动画开始之前执行。 更新2: 这个版本可以在没有setTimeout()调用的情况下工作:http://jsfiddle.net/2mhcv/2/。意识到只需要进行重绘,我在那里添加了一行来读取计算出的CSS属性,比如display。 您可以读取任何其他计算属性以获得相同的效果。

这似乎不太起作用。从概念上讲,我需要做四件事:1)删除“movable”类,2)设置起始位置,3)恢复可移动类,4)设置结束位置(应该过渡)。问题似乎是当您在JavaScript函数中执行所有四个步骤时-它似乎没有执行所有步骤。相反,它将它们“净化”。也就是说,它得出结论,即1)和3)的“净”结果是该类应该具有“movable”类,而2)和4)的“净”结果是元素应该只移动到结束位置。 - mattstuehler
换句话说,它似乎只是忽略了步骤1和2。另一方面,如果我执行步骤1和2,然后创建一个在短暂延迟(200毫秒)后执行3和4的超时 - 它可以工作。但我不喜欢使用延迟。 - mattstuehler
我从未见过Javascript或jquery捕获连续操作的结果。它们可能发生得非常快,以至于您无法看到它们。您能否创建一个fiddle,让我可以验证您所看到的内容? - Chandranshu
Chandranshu - 首先 - 感谢您的帮助。这是我设置的两个 fiddles。在这一个里,我在单个函数中执行了所有4个步骤:http://jsfiddle.net/bUvX3/ 在下一个 fiddles 里,在50ms延迟后我执行步骤3和4:http://jsfiddle.net/2mhcv/ 正如您所看到的,只有延迟的那一个似乎起作用。当然,我可能只是犯了一个愚蠢的错误... - mattstuehler
啊,我明白了。你想要的和我建议的有所不同,因此我建议的和你实现的也有所不同。我并不想使用变换样式来移动div。我认为div放置在某个容器中,我们知道它当前的左/右位置,只需更改即可。一组变换(特别是3D变换)将同时执行,除非有意引入延迟。 - Chandranshu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接