Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reverse Keyframe animation with Javascript

I animate a block with a keyframe, then trigger the reversed animation in javascript, like this :

$('#block').removeClass('animate1').addClass('animate2');

With animate1 and animate2 corresponding to two CSS classes calling the animation (for the demo, in webkit only), and #block a simple div:

CSS

.animate1 {
    -webkit-animation: shift 1s ease-in-out forwards;
}
.animate2 {
    -webkit-animation: shift 1s ease-in-out backwards reverse;
}
@-webkit-keyframes shift {
    from {
        left: 0px;
    }
    to {
        left: 200px;
    }
}

HTML

<div id="block" class="animate2"></div>

It simply doesn't work. See this fiddle for demo (Chrome 30).


Facts

If I trigger the animations the other way around, I mean the reversed one first, then the normal one, it's working properly (demo):

$('#block').removeClass('animate2').addClass('animate1'); //Works.

It's working too if I remove the current class and add the next class with independent functions triggered by click on buttons.

Can someone help me understand this strange behavior? I'm stuck!


Edit

For future visitors, I'm not looking for a workaround anymore, just trying to find out what's happening here:

  • What is this "reset time" required by browser?
  • Why does it works in a way, and not in the other?
  • Why triggering the animation within an inner closure works?

I'll change the accepted answer if appropriate.

like image 978
Bigood Avatar asked Dec 28 '13 01:12

Bigood


People also ask

How do you invert keyframes?

Reverse keyframes In the Keyframe Editor in MotionMotionMotion is a software application produced by Apple Inc. for their macOS operating system. It is used to create and edit motion graphics, titling for video production and film production, and 2D and 3D compositing for visual effects.https://en.wikipedia.org › wiki › Motion_(software)Motion (software) - Wikipedia, drag a selection rectangle to select the keyframes to reverse. Control-click a selected keyframe, then choose Reverse Keyframes from the shortcut menu. The keyframes are reversed.

What is animation direction CSS?

The animation-direction CSS property sets whether an animation should play forward, backward, or alternate back and forth between playing the sequence forward and backward.


2 Answers

When you are reusing an animation, sometimes you inherit the state of it.

The way this happens is a little difficult to forecast, because it isn't always consistent (I guess also that the w3c standard doesn't set exactly what should happen in this cases).

In your case, you are reusing an animation that should happen once (animation-iteration-count : initial, i.e. 1), and that has already happened once. So, nothing happens. (It is true that the other way round works, but as I said before that issue is not always consistent.)

One way to solve it is to reset the transition.

setTimeout(function () {
    $('#block').removeClass('animate1');
}, 1950);
setTimeout(function () {
    $('#block').addClass('animate2');
}, 2000);

That leaves the div without any animation for a moment, and so reset efectively the transition. You have now the problem that the div jumps to the initial state, so this is not usable right as it is; but I am trying to explain why you have the problem.

A working solution can be going thru transitions, as Jacob says, or creating to different animations.

jumping demo

like image 175
vals Avatar answered Oct 05 '22 23:10

vals


CSS3 animations appear to be intended for one-off or infinitely looping animations, as suggested by MDN's "Using CSS animations" developer guide.

To keep the logic as you have it, I'd switch to CSS3 transitions.

First, in CSS, let's define two alternate "states" our cat photo can be in (on the left, or on the right):

.transition1 {
    transition-property: left;
    transition-duration: 1s;
    left: 0px;
}
.transition2 {
    transition-property: left;
    transition-duration: 1s;
    left: 200px;
}

Now, using your JS, with our renamed CSS classes:

$('#swap1').click(function () {
    $('#block').removeClass('transition1').addClass('transition2');
});
$('#swap2').click(function () {
    $('#block').removeClass('transition2').addClass('transition1');
});

On button click, the (cat photo) element's left property will transition from 0px to 200px (or vice-versa) over one second time. Here's my code: http://jsfiddle.net/u6jsC/.

like image 39
Jacob Budin Avatar answered Oct 05 '22 23:10

Jacob Budin