Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
465 views
in Technique[技术] by (71.8m points)

jquery - How can I change the speed of a CSS animation?

I have animation:

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);
  }
}

I have an rotating image at infinite. Now I want change the speed of rotation with JS. I tried:

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

The duration changes the speed, but the animation reboot to framekey 0% (the first), but I just want the animation continue like nothing happened; I don't want to go back to 0%.

How can I do that?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It's a very difficult process to do so. Currently the only way to change an animation mid-animation is to use a setInterval to approximate the current keyframes percentage, save the properties of that keyframe, update the animation (in your case just the speed) then apply the new version of the animation starting from the saved point. I created a similar example in the article I wrote for CSS Tricks called Controlling CSS Animations & Transitions with Javascript

As the article described, it'd be easier to change the speed on animationIteration, in your case that would look like this demo, but it is still far from pretty

 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();

At the moment we cannot simply restart the animation with a different timing function (even if you pause it and run it again like Michael said). As a result you either have to use a setInterval (which gives a higher delay) or clone the element with the changed values. For more information on the approach I used look at the demo, I added comments to all the javascript I added

EDIT based on your linked fiddle in comments

Since you're trying to simulate a roulette, you don't need to use javascript at all! Simply change your rotation animation to change speed over time (: Here's an rough version of how you'd do so, but you should add more keyframes to make it appear more smooth than it currently behaves

@-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); }
}

EDIT 2

Since you need apparently need have a random ending position and likely run it multiple times you can do something like this which is much simpler, only uses CSS transforms, and incredibly useful

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
    );
}

and the CSS

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

Edit 3

This isn't fully relevant or irrelevant, but you can do very similar things using GSAP like I did in this project to make it more interactive/dynamic


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...