如何改变CSS动画的速度?

16

我有动画:

img.rotate {
  animation-name: rotate;
  animation-duration: 1.5s;
  animation-iteration-count: infinite;
  animation-timing-function: linear;
}

@keyframes rotate {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

我有一张无限旋转的图片。现在我想用JS改变旋转速度。我尝试过:

$('img').css('animation-duration', '2s');

时间长度会改变动画的速度,但是动画重新启动到0%关键帧(第一个),我只想让动画继续运行,就像没有发生过任何事情一样; 我不想回到0%。

我该怎么做?

2个回答

11
这是一个非常困难的过程。目前唯一更改动画中间状态的方法是使用setInterval来近似当前关键帧百分比,保存该关键帧的属性,更新动画(在您的情况下只需更改速度),然后从保存点开始应用新版本的动画。我在为CSS Tricks撰写的文章中创建了一个类似的示例,名为通过Javascript控制CSS动画和过渡
正如文章所述,在animationIteration上更改速度会更容易,对于您的情况,它看起来像这个演示,但仍然远非完美。
 var pfx = ["webkit", "moz", "MS", "o", ""],
    rotates = $('.rotate'),
    prevent = false;

function PrefixedEvent(element, type, callback) {
    for (var p = 0; p < pfx.length; p++) {
        if (!pfx[p]) type = type.toLowerCase();
        element.addEventListener(pfx[p]+type, callback, false);
    }
}

function listen() {
    for(var i = 0, j = rotates.length; i < j; i ++) {
        PrefixedEvent(rotates[i], "AnimationIteration", function() {
            if(!$('#faster').is(':checked') && !prevent) {
                var el = $(this),  
                   newOne = el.clone(true)
                            .css({'animation':'rotate 2s linear infinite'});
                el.before(newOne);        
                $("." + el.attr("class") + ":last").remove();
                rotates = $('.rotate');
                listen();
                prevent = true;
            }
            else if($('#faster').is(':checked') && prevent) {
                prevent = false;
                var el = $(this),
                   newOne = el.clone(true)
                            .css({'animation':'rotate 1.5s linear infinite'});
                el.before(newOne);
                $("." + el.attr("class") + ":last").remove();
                rotates = $('.rotate');
                listen();
            }
        });
    }
}
listen();

目前我们无法简单地使用不同的时间函数重新启动动画(即使像Michael说的那样暂停它并再次运行)。因此,您要么必须使用setInterval(这会导致更高的延迟),要么克隆具有更改值的元素。有关我使用的方法的更多信息,请查看演示文稿,我已添加了所有添加的javascript的注释。
根据您在评论中提供的链接fiddle进行编辑
由于您正在尝试模拟轮盘赌,因此根本不需要使用javascript!只需将您的rotation动画更改为随时间变化的速度即可(: 这是一个粗略版本,但您应该添加更多关键帧,以使其表现比当前更平滑。
@-webkit-keyframes rotate {
    0%   { -webkit-transform: rotate(   0deg); }
    30%  { -webkit-transform: rotate(2600deg); }
    60%  { -webkit-transform: rotate(4000deg); }
    80%  { -webkit-transform: rotate(4500deg); }
    100% { -webkit-transform: rotate(4780deg); }
}

编辑2

由于你需要似乎需要一个随机的结束位置并且可能需要运行多次,你可以做类似于这样的事情,这更简单,仅使用CSS变换,并且非常有用。

var img = document.querySelector('img');
img.addEventListener('click', onClick, false);    
var deg = 0;

function onClick() {
    this.removeAttribute('style');        
    deg += 5 * Math.abs(Math.round(Math.random() * 500));        
    var css = '-webkit-transform: rotate(' + deg + 'deg);';        
    this.setAttribute(
        'style', css
    );
}

和CSS

img { -webkit-transition: -webkit-transform 2s ease-out; }

编辑3

这并非完全相关或无关紧要,但您可以使用GSAP来执行非常相似的操作,就像我在此项目中所做的那样以使其更具交互性/动态性。


这个解决方案行不通。你没有完成整个工作。我想使用事件JS并等待一次迭代的结束以减速(增加持续时间)重新启动动画,但这是一个虚假的好主意:因为我想将旋转减少到0,所以当你减速时,结束一次迭代的时间(为了更多地减少)会增加。测试一下...你就会明白。 - Matrix
我这么做只是为了展示问题:http://jsfiddle.net/52xLK/31/。它永远不会停止,而且随着时间的推移,速度会越来越慢。 - Matrix
@Matrix 我更新了我的答案,提供了一个更合适的仅使用CSS的解决方案。 - Zach Saucier
你的新示例有一个糟糕的结尾:它在第一关键帧结束(它不是连续动画,而是跳跃式的)。此外,如果我想要随机的结束位置,也做不到。 - Matrix
1
@Matrix,我又更新了。希望这次是你需要的。下次请更清楚地表达你的最终目标,这样我们才能帮助你解决实际问题。 - Zach Saucier
是的,它可以工作,但这并不是真正的控制速度的方法。对于另一种动画,我不确定这个“欺骗”是否可行。谢谢帮助。 - Matrix

4

您可以通过设置包装器并将其反向旋转来实现。

CSS

.wrapper, .inner {
    position: absolute;
    width: 100px;
    height: 100px;
  -webkit-animation-name: rotate;
  -webkit-animation-iteration-count: infinite;
  -webkit-animation-timing-function: linear;
  animation-name: rotate;
  animation-iteration-count: infinite;
  animation-timing-function: linear;
}
.wrapper {
    left: 40px;
    top: 40px;
  -webkit-animation-duration: 2.5s;
    -webkit-animation-play-state: paused;
    -webkit-animation-direction: reverse;
  animation-duration: 2.5s;
    animation-play-state: paused;
    animation-direction: reverse;
}
.wrapper:hover {
    -webkit-animation-play-state: running;
    animation-play-state: running;
}
.inner {
    display: block;
    background-color: red;
  -webkit-animation-duration: 1.5s;
  animation-duration: 1.5s;
}
@keyframes rotate {
  from { transform: rotate(0deg);  }
  to {    transform: rotate(360deg);  }
}    
@-webkit-keyframes rotate {
  from { -webkit-transform: rotate(0deg);  }
  to {    -webkit-transform: rotate(360deg);  }
}

演示

(将鼠标悬停在正方形上以减缓速度)


好的,但是如果我想逐渐将速度降低到0,我该怎么做呢? - Matrix

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