Reputation: 10698
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
:
.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;
}
}
<div id="block" class="animate2"></div>
It simply doesn't work. See this fiddle for demo (Chrome 30).
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!
For future visitors, I'm not looking for a workaround anymore, just trying to find out what's happening here:
I'll change the accepted answer if appropriate.
Upvotes: 6
Views: 5967
Reputation: 64164
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.
Upvotes: 3
Reputation: 10003
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/.
Upvotes: 1