CSS过渡动画在JavaScript添加属性连续变化时无效。

3
下面是我网站遇到的一个问题的简化版本。

function move(){
  document.getElementById("box").style.transition = "0s";
  document.getElementById("box").style.top = "100px";
  document.getElementById("box").style.transition = "2s";
  document.getElementById("box").style.top = "0px";
}
#box{
  width:100px;
  height:100px;
  background:red;
  position:relative;
  top:0px;
}
<div id="box" onclick="move()"></div>

我希望它能够使方框立即向下跳,并缓慢移回其起始位置。我已经单独测试了move()中的四行代码,它们都完美地工作。我只是不能让它们一起运行。
我做错了什么?

可能是重复的问题:https://stackoverflow.com/q/8210560/6190320 - undefined
2个回答

5

看起来代码需要在分配新属性之前延迟,以便浏览器可以处理请求。因此,您需要使用setTimeout()来解决这个问题。

function move(){
  document.getElementById("box").style.transition = "0s";
  document.getElementById("box").style.top = "100px";
  setTimeout(function(){
    document.getElementById("box").style.transition = "2s";
    document.getElementById("box").style.top = "0px";
  }, 10);
}
#box{
  width:100px;
  height:100px;
  background:red;
  position:relative;
  top:0px;
}
<div id="box" onclick="move()"></div>


我想我明白了。唯一让我困惑的是为什么是10毫秒?为什么不是1毫秒? - Jonathon Philip Chambers
@JonathonPhilipChambers 如果它能工作,你可以使用1毫秒。我使用了10毫秒来确保代码能够正常运行。 - Mohammad
这个解决方案很好用。我将它从10毫秒改成了1毫秒,目前还没有出现任何问题。(虽然我感觉不出区别,但1毫秒的代码对我来说更加清晰易懂。) - Jonathon Philip Chambers

3

不要依赖过渡效果,最好使用@keyframesanimation,这样你不必使用肮脏的技巧,例如在动画进行时将过渡持续时间从0更改为实际值以实现跳跃。以下是一个利用@keyframes CSS特性的示例:

function move(){
  document.getElementById("box").style.animation = "movement 2s";
}
#box{
  width:100px;
  height:100px;
  background:red;
  position:relative;
  top:0px;
}
@keyframes movement {
    from {top: 100px;}
    to {top: 0px;}
}
<div id="box" onclick="move()"></div>


我很感兴趣,但为什么它只在第一次点击时起作用? - Jonathon Philip Chambers
另外,如果起点和/或终点位置是由JavaScript确定的,它会起作用吗? - Jonathon Philip Chambers
它只在第一次点击时起作用,因为一旦类被添加,重新添加它不会改变应用的CSS规则,所以如果没有任何变化,那么就不会发生动画。因此,要处理多次点击,您需要在动画完成后删除该类。而要在JavaScript中更改位置,可以使用CSS变量。这两个问题的解决方案可以在此Codepen中找到:https://codepen.io/anon/pen/QJqbWM - Piotr Wicijowski

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