Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change the execution time of an infinite animation(in CSS3) smoothly with Javascript

I have searched through a lot of questions related to my question in stackoverflow but i haven't found one yet that answers my question with plain JavaScript (not using libraries of any kind).

My problem is that I have an infinite animation with CSS3 i.e.:

.clockwiseAnimation {
    top: 270px;
    left: 200px;
    position: absolute;

    -webkit-animation: clockwise 4s linear infinite; /* Chrome, Safari 5 */
    -moz-animation: clockwise 4s linear infinite; /* Firefox 5-15 */
    -o-animation: clockwise 4s linear infinite; /* Opera 12+ */
    animation: clockwise 4s linear infinite; /* Chrome, Firefox 16+, IE 10+, Safari 5 */
}
@-webkit-keyframes clockwise {
    from { -webkit-transform: rotate(0deg) translateX(150px) rotate(0deg); }
    to { -webkit-transform: rotate(360deg) translateX(150px) rotate(-360deg); }
}
@-moz-keyframes clockwise {
    from { -moz-transform: rotate(0deg) translateX(150px) rotate(0deg); }
    to { -moz-transform: rotate(360deg) translateX(150px) rotate(-360deg); }
}
@-o-keyframes clockwise {
    from { -o-transform: rotate(0deg) translateX(150px) rotate(0deg); }
    to { -o-transform: rotate(360deg) translateX(150px) rotate(-360deg); }
}
@keyframes clockwise {
    from { transform: rotate(0deg) translateX(150px) rotate(0deg); }
    to { transform: rotate(360deg) translateX(150px) rotate(-360deg); }
}

This animation allows me to spin (clockwise) whatever tag that has the class "clockwiseAnimation".

What I want to do is to change the time of execution (I'll call it speed) of the animation with javascript like:

HTML:

<span id="someID" class="clockwiseAnimation">sometext</span>

JavaScript:

var style = document.getElementById("someID").style,
speed = 6; 
//obviously the speed is dynamic within my site (through an `<input type="range">`)
//for the purposes of this example I set the speed to a different value(6seconds) than the original value(4seconds).
style.webkitAnimationDuration = style.mozAnimationDuration = style.oAnimationDuration = style.animationDuration = speed + "s";

It works when I pause and then play(by play I mean UNPAUSE not restart) the animation, i.e.:

var style = document.getElementById("someID").style;
some = 6; //it is dynamic (as I pointed out before)

//pause
style.webkitAnimationPlayState = style.mozAnimationPlayState = style.oAnimationPlayState = style.animationPlayState = "paused";

//change speed
style.webkitAnimationDuration = style.mozAnimationDuration = style.oAnimationDuration = style.animationDuration = speed + "s";  

//play (== UNPAUSE) //UPDATE: Added the timeout because I can't get it to work any other way.
setTimeout(function(){
            style.webkitAnimationPlayState = style.mozAnimationPlayState = style.oAnimationPlayState = style.animationPlayState = "running";
        },1);

UPDATED:

And it works! BUT, it has a big RANDOM jump in the animation, meaning that when I change the "speed" with the "<input type="range"> slider" the element jumps to a random location (not the beginning nor the end of the animation just a random location).

NOTE: Pause and play works very smooth without changing the "speed" of the animation.

My question(s): Can I change the "speed" of the animation smoothly WITH JavaScript? (WITHOUT the jumping) If the answer is: "There is not a way to do it smoothly throughout the animation execution", then: Is there a way to change it in the next iteration of the infinite animation? If so: Then how can I tell it to start in the next iteration and how to know which is the next iteration if I set the animation to infinite (animation-iteration-count property of the element that is doing the animation always returns "infinite").

Here is an example. I hope it helps.

like image 747
pgarciacamou Avatar asked Jan 23 '14 01:01

pgarciacamou


People also ask

How do you animate smoothly in CSS?

The animation-timing-function specifies the speed curve of an animation. The speed curve defines the TIME an animation uses to change from one set of CSS styles to another. The speed curve is used to make the changes smoothly.

Is CSS animation faster than JavaScript?

The fact is that, in most cases, the performance of CSS-based animations is almost the same as JavaScripted animations — in Firefox at least. Some JavaScript-based animation libraries, like GSAP and Velocity. JS, even claim that they are able to achieve better performance than native CSS transitions/animations.

How do I stop infinite animation CSS?

The basics of pausing an animation The only way to truly pause an animation in CSS is to use the animation-play-state property with a paused value. In JavaScript, the property is “camelCased” as animationPlayState and set like this: element. style.

Does css3 animation need JavaScript?

CSS allows animation of HTML elements without using JavaScript or Flash! In this chapter you will learn about the following properties: @keyframes.


1 Answers

What may be occurring is that the animation-duration "change" could be "jumping" to the point in the animation corresponding to the "changed" @keyframes - based on the total "changed" animation duration..

If the animation-duration began from (or 0%) proceeded to to (or 100%), the corresponding @keyframes "position" may be changed as well.

For example if the original animation-duration was 4s (or, 4000ms) at approximately 2s (or, 2000ms), the corresponding keyframes may be at approximately 50%, or

at 2 seconds into 4 second animation 50% { -webkit-transform: rotate(180deg) translateX(150px) rotate(-180deg); }

when the animation-duration is dynamically changed, the corresponding keyframes may be "changed" to the matching % point, or, a larger duration span for the same effect. The animated element may appear to go forwards or backwards, or hve a "jumping" due to it re-positioning itself within the "changed" corresponding keyframes and animations.

There is also 1s setTimeout function, that may or may not actually have a 1s duration.

It may be possible to "smoothly" "jump" to the newly "changed" position within the lengthier animation-duration the suggested transition effect or requestAnimationFrame (http://www.w3.org/TR/animation-timing/).

..

Try this:

html

<input type="range" id="speedSlider" min="2000" max="6000" value="4000">

css

    input {
    -webkit-transform: rotate(180deg);  
    top : 50px;
    position : absolute;
}

.clockwiseAnimation {
 /* top: 270px;
    left: 200px; */
    left : 50%;
    top : 50%;
    position:absolute;

   /* css animation (no change) */
}

js

var speedSlider = document.getElementById("speedSlider");
    speedSlider.addEventListener("change", changeSpeed, false);
    function changeSpeed(e){
        var speed = Math.floor(speedSlider.value);
        var element = document.getElementById("span");
        var style = element.style;
        style.webkitAnimationPlayState = style.mozAnimationPlayState = style.oAnimationPlayState = style.animationPlayState = "paused";
        style.webkitAnimationDuration = style.mozAnimationDuration = style.oAnimationDuration = style.animationDuration = String(speed) + "ms";
            style.webkitAnimationPlayState = style.mozAnimationPlayState = style.oAnimationPlayState = style.animationPlayState = "running";
    }
like image 71
guest271314 Avatar answered Sep 28 '22 07:09

guest271314