admin管理员组文章数量:1025227
I need to create a rotation animation. A click event spins an element 180° to point down. Another click event spins the same element back to 0° to point up.
I have animation-fill-mode
to set to forwards
to preserve the last keyframe state. But it does not appear to be working. All visual elements reset to the default state.
Any ideas what I may be doing wrong?
My Codepen:
My code:
(function() {
$('#btnb').on('click', function(e) {
return $('.box').addClass('spin-counter-clockwise');
});
$('#btnf').on('click', function(e) {
return $('.box').addClass('spin-clockwise');
});
$('.box').on('webkitAnimationEnd', function(e) {
return $(e.target).removeClass('spin-counter-clockwise').removeClass('spin-clockwise');
});
}.call(this));
.box {
background: red;
position: relative;
width: 176px;
height: 176px;
margin: 40px auto;
text-align: center;
}
.box .top {
background: green;
position: absolute;
top: 0;
width: 100%;
height: 28px;
}
.box .bottom {
background: purple;
position: absolute;
bottom: 0;
width: 100%;
height: 28px;
}
.box .caret {
color: white;
font-size: 88px;
position: absolute;
top: 42px;
left: 50px;
}
.spin-clockwise {
-moz-animation: spin 2s;
-webkit-animation: spin 2s;
-moz-animation-fill-mode: forwards;
-webkit-animation-fill-mode: forwards;
}
.spin-counter-clockwise {
-moz-animation: spin 2s reverse;
-webkit-animation: spin 2s reverse;
-moz-animation-fill-mode: forwards;
-webkit-animation-fill-mode: forwards;
}
@keyframes spin {
from {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
to {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
}
body {
text-align: center;
margin: 0 auto;
}
<link href=".5.0/css/font-awesome.min.css" rel="stylesheet" />
<script src=".1.1/jquery.min.js"></script>
<h2>Keyframes are not supported in IE9 and earlier</h2>
<div class="box">
<div class="top">top</div>
<div class="caret"><i class="fa fa-caret-square-o-up"></i>
</div>
<div class="bottom">bottom</div>
</div>
<p>
<button id="btnf">SPIN CLOCKWISE</button>
</p>
<p>
<button id="btnb">SPIN COUTNER CLOCKWISE</button>
</p>
I need to create a rotation animation. A click event spins an element 180° to point down. Another click event spins the same element back to 0° to point up.
I have animation-fill-mode
to set to forwards
to preserve the last keyframe state. But it does not appear to be working. All visual elements reset to the default state.
Any ideas what I may be doing wrong?
My Codepen: http://codepen.io/simspace-dev/pen/RrpGmP
My code:
(function() {
$('#btnb').on('click', function(e) {
return $('.box').addClass('spin-counter-clockwise');
});
$('#btnf').on('click', function(e) {
return $('.box').addClass('spin-clockwise');
});
$('.box').on('webkitAnimationEnd', function(e) {
return $(e.target).removeClass('spin-counter-clockwise').removeClass('spin-clockwise');
});
}.call(this));
.box {
background: red;
position: relative;
width: 176px;
height: 176px;
margin: 40px auto;
text-align: center;
}
.box .top {
background: green;
position: absolute;
top: 0;
width: 100%;
height: 28px;
}
.box .bottom {
background: purple;
position: absolute;
bottom: 0;
width: 100%;
height: 28px;
}
.box .caret {
color: white;
font-size: 88px;
position: absolute;
top: 42px;
left: 50px;
}
.spin-clockwise {
-moz-animation: spin 2s;
-webkit-animation: spin 2s;
-moz-animation-fill-mode: forwards;
-webkit-animation-fill-mode: forwards;
}
.spin-counter-clockwise {
-moz-animation: spin 2s reverse;
-webkit-animation: spin 2s reverse;
-moz-animation-fill-mode: forwards;
-webkit-animation-fill-mode: forwards;
}
@keyframes spin {
from {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
to {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
}
body {
text-align: center;
margin: 0 auto;
}
<link href="https://maxcdn.bootstrapcdn./font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h2>Keyframes are not supported in IE9 and earlier</h2>
<div class="box">
<div class="top">top</div>
<div class="caret"><i class="fa fa-caret-square-o-up"></i>
</div>
<div class="bottom">bottom</div>
</div>
<p>
<button id="btnf">SPIN CLOCKWISE</button>
</p>
<p>
<button id="btnb">SPIN COUTNER CLOCKWISE</button>
</p>
Share
Improve this question
edited Jan 6, 2016 at 6:22
Harry
89.9k26 gold badges214 silver badges223 bronze badges
asked Jan 5, 2016 at 23:18
Chris SimeoneChris Simeone
1,2052 gold badges16 silver badges29 bronze badges
3
- Is there any specific reason why you've used animations? It would be much easier to achieve this with transitions instead of animation. – Harry Commented Jan 6, 2016 at 4:29
- 1 Thanks Harry, I will look into transitions. – Chris Simeone Commented Jan 6, 2016 at 6:23
- 1 Thanks for the great answers Harry, Chris and oMiKeY! If it turns out I use transitions (which sounds like the better method), I'm still glad I attempted this route for the learning experience. I never messed around with CSS animations prior to this and I learned much. – Chris Simeone Commented Jan 6, 2016 at 6:34
3 Answers
Reset to default 3TL;DR: (straight to the suggested solution)
If all you need is a rotation from 0° to 180° on the click of one button and back from 180° to 0° on the other then I would suggest using transitions instead of animations. Transitions by default produce the reverse effect and so there is no need to code for two different states (which makes it even better).
(function() {
$('#btnb').on('click', function(e) {
return $('.box').removeClass('spin');
});
$('#btnf').on('click', function(e) {
return $('.box').addClass('spin');
});
}.call(this));
.box {
background: red;
position: relative;
width: 176px;
height: 176px;
margin: 40px auto;
text-align: center;
transition: transform 1s linear;
/* add this to enable transition */
}
.box .top {
background: green;
position: absolute;
top: 0;
width: 100%;
height: 28px;
}
.box .bottom {
background: purple;
position: absolute;
bottom: 0;
width: 100%;
height: 28px;
}
.box .caret {
color: white;
font-size: 88px;
position: absolute;
top: 42px;
left: 50px;
}
.spin {
/* this is the only thing required for rotation (along with the JS) */
transform: rotate(180deg);
}
body {
text-align: center;
margin: 0 auto;
}
<link href="https://maxcdn.bootstrapcdn./font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h2>Keyframes are not supported in IE9 and earlier</h2>
<div class="box">
<div class="top">top</div>
<div class="caret"><i class="fa fa-caret-square-o-up"></i>
</div>
<div class="bottom">bottom</div>
</div>
<p>
<button id="btnf">SPIN CLOCKWISE</button>
</p>
<p>
<button id="btnb">SPIN COUTNER CLOCKWISE</button>
</p>
If you were using animations only for learning purpose, the details provided below should still be useful to you in terms of understanding how animations work, what are the limitations because of it etc.
Chris' answer touches upon the reason for your problem but I thought the question merited a bit more detailed explanation of two things - (1) Why the element doesn't hold the state as at the last keyframe even though animation-fill-mode: forwards
setting is applied (2) Why the same keyframe couldn't be used for the reverse animation (when the class with the original animation was not removed). I also wanted to suggest a different alternate to the whole thing and hence the separate answer.
Why does the element not hold the state as at the last keyframe even though fill mode is set to forwards?
This is because you are removing the class that adds the animation as soon as animation pletes (inside the on('webkitAnimationEnd')
event handler). Generally when animation-fill-mode
is set to forwards
, the UA uses the settings (or property-value pair) that are provided within last keyframe to maintain the state. But once the class is removed (and in-turn the animation settings), the UA does not keep track of (or know what) animations that were prior present on the element, their state and fill mode etc. Once animation is removed, the browser triggers a repaint and this will be performed based on classes that are present on the element as at the time of the repaint. Due to this, the element would snap back to its un-rotated state. You can read more about it in my answer here to a similar question (but not the same :)).
Why can't the same keyframe be used for the reverse animation (when the class which had the original animation was not removed)?
This again is because of how animations generally work. When any animation is added to an element, the UA maintains details about the animation's keyframes, its state etc as long as it is attached to the element. So, unless the class which added the forward (0° to 180°) animation is removed, the browser thinks that it has executed the animation to pletion (as default iteration count is just 1) and so even when a class with the reverse animation is added, it does nothing. The only way to make it restart the animation in reverse direction is by removing the class with the forward animation and then adding the class with the reverse animation. You can have a look at this answer also for related reading.
Because of the aforementioned reasons, the only way to achieve what you need with animations is to create two different animations (or keyframes) for the forward and reverse animations, set them under two different classes and keep changing the classes using JavaScript. This whole process bees tedious and is generally not necessary when all you need is a rotation from (0° to 180°) on the click of one button and back from (180° to 0°) on the other. This whole thing can be achieved using transitions and what makes this even better is the fact that transitions by default produce the reverse effect and so there is no need to code for two different states.
Further Reading:
What are the differences between Transitions and Animations
Choosing Transitions or Animations - When to use which?
If the need is to have continuous clockwise or counter-clockwise rotations with each button click (like in oMiKeY's answer) then I'd still remend using transition with a bit of JS like in the below snippet. Let's leave animations for more plex stuff (and in specific stuff that'd happen without any triggers).
(function() {
var deg = 0;
$('#btnb').on('click', function(e) {
deg -= 180;
return $('.box').css('transform', 'rotate(' + deg + 'deg)');
});
$('#btnf').on('click', function(e) {
deg += 180;
return $('.box').css('transform', 'rotate(' + deg + 'deg)');
});
}.call(this));
.box {
background: red;
position: relative;
width: 176px;
height: 176px;
margin: 40px auto;
text-align: center;
transition: transform 1s linear; /* add this to enable transition */
}
.box .top {
background: green;
position: absolute;
top: 0;
width: 100%;
height: 28px;
}
.box .bottom {
background: purple;
position: absolute;
bottom: 0;
width: 100%;
height: 28px;
}
.box .caret {
color: white;
font-size: 88px;
position: absolute;
top: 42px;
left: 50px;
}
body {
text-align: center;
margin: 0 auto;
}
<link href="https://maxcdn.bootstrapcdn./font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h2>Keyframes are not supported in IE9 and earlier</h2>
<div class="box">
<div class="top">top</div>
<div class="caret"><i class="fa fa-caret-square-o-up"></i>
</div>
<div class="bottom">bottom</div>
</div>
<p>
<button id="btnf">SPIN CLOCKWISE</button>
</p>
<p>
<button id="btnb">SPIN COUTNER CLOCKWISE</button>
</p>
So the root issue was the class with the animation was being removed.
I couldn't get it to work using the same keyframes, but what i did was create a new keyframes for counter clockwise, and then removed the opposite class when the buttons were clicked
Changes:
css
.spin-clockwise {
-moz-animation: spin 2s;
-webkit-animation: spin 2s;
}
.spin-fill-mode {
-moz-animation-fill-mode: forwards;
-webkit-animation-fill-mode: forwards;
animation-fill-mode: forwards;
}
.spin-counter-clockwise {
-moz-animation: spin-counter 2s;
-webkit-animation: spin-counter 2s;
}
@keyframes spin {
from {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
to {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
}
@keyframes spin-counter {
from {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
to {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
}
js:
$('#btnb').on('click', (e)->
$('.box')
.addClass('spin-counter-clockwise')
.removeClass('spin-clockwise')
)
$('#btnf').on('click', (e) ->
$('.box')
.addClass('spin-clockwise')
.removeClass('spin-counter-clockwise')
)
And add the class spin-fill-mode to box. Though you could probably just leave the fill-mode in the animation classes... updated codepen:
http://codepen.io/anon/pen/QypvOr
I fiddled with it for a while then decided you might need two separate rotation animations.
Check out my fiddle: http://codepen.io/anon/pen/jWBmZK
(function() {
$('#btnb').on('click', function(e) {
return $('.box')
.addClass('spin-counter-clockwise')
.toggleClass('upside-down');
});
$('#btnf').on('click', function(e) {
return $('.box')
.addClass('spin-clockwise')
.toggleClass('upside-down');
});
$('.box').on('webkitAnimationEnd', function(e) {
return $(e.target).removeClass('spin-counter-clockwise').removeClass('spin-clockwise');
});
}.call(this));
.box {
background: red;
position: relative;
width: 176px;
height: 176px;
margin: 40px auto;
text-align: center;
}
.box .top {
background: green;
position: absolute;
top: 0;
width: 100%;
height: 28px;
}
.box .bottom {
background: purple;
position: absolute;
bottom: 0;
width: 100%;
height: 28px;
}
.box .caret {
color: white;
font-size: 88px;
position: absolute;
top: 42px;
left: 50px;
}
.upside-down {
-moz-transform: rotate(180deg);
-webkit-transform: rotate(180deg);
-ms-transform: rotate(180deg);
-o-transform: rotate(180deg);
transform: rotate(180deg);
}
.spin-clockwise.upside-down {
-moz-animation: spin 2s;
-webkit-animation: spin 2s;
-moz-animation-fill-mode: forwards;
-webkit-animation-fill-mode: forwards;
}
.spin-counter-clockwise {
-moz-animation: spin 2s reverse;
-webkit-animation: spin 2s reverse;
-moz-animation-fill-mode: forwards;
-webkit-animation-fill-mode: forwards;
}
.spin-clockwise {
-moz-animation: back-spin 2s;
-webkit-animation: back-spin 2s;
-moz-animation-fill-mode: forwards;
-webkit-animation-fill-mode: forwards;
}
.spin-counter-clockwise.upside-down {
-moz-animation: back-spin 2s reverse;
-webkit-animation: back-spin 2s reverse;
-moz-animation-fill-mode: forwards;
-webkit-animation-fill-mode: forwards;
}
@keyframes spin {
from {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
to {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
}
@keyframes back-spin {
from {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
to {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
body {
text-align: center;
margin: 0 auto;
}
<link href="https://maxcdn.bootstrapcdn./font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<body>
<h2>Keyframes are not supported in IE9 and earlier</h2>
<div class="box">
<div class="top">top</div>
<div class="caret"><i class="fa fa-caret-square-o-up"></i>
</div>
<div class="bottom">bottom</div>
</div>
<p>
<button id="btnf">SPIN CLOCKWISE</button>
</p>
<p>
<button id="btnb">SPIN COUTNER CLOCKWISE</button>
</p>
</body>
</html>
I need to create a rotation animation. A click event spins an element 180° to point down. Another click event spins the same element back to 0° to point up.
I have animation-fill-mode
to set to forwards
to preserve the last keyframe state. But it does not appear to be working. All visual elements reset to the default state.
Any ideas what I may be doing wrong?
My Codepen:
My code:
(function() {
$('#btnb').on('click', function(e) {
return $('.box').addClass('spin-counter-clockwise');
});
$('#btnf').on('click', function(e) {
return $('.box').addClass('spin-clockwise');
});
$('.box').on('webkitAnimationEnd', function(e) {
return $(e.target).removeClass('spin-counter-clockwise').removeClass('spin-clockwise');
});
}.call(this));
.box {
background: red;
position: relative;
width: 176px;
height: 176px;
margin: 40px auto;
text-align: center;
}
.box .top {
background: green;
position: absolute;
top: 0;
width: 100%;
height: 28px;
}
.box .bottom {
background: purple;
position: absolute;
bottom: 0;
width: 100%;
height: 28px;
}
.box .caret {
color: white;
font-size: 88px;
position: absolute;
top: 42px;
left: 50px;
}
.spin-clockwise {
-moz-animation: spin 2s;
-webkit-animation: spin 2s;
-moz-animation-fill-mode: forwards;
-webkit-animation-fill-mode: forwards;
}
.spin-counter-clockwise {
-moz-animation: spin 2s reverse;
-webkit-animation: spin 2s reverse;
-moz-animation-fill-mode: forwards;
-webkit-animation-fill-mode: forwards;
}
@keyframes spin {
from {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
to {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
}
body {
text-align: center;
margin: 0 auto;
}
<link href=".5.0/css/font-awesome.min.css" rel="stylesheet" />
<script src=".1.1/jquery.min.js"></script>
<h2>Keyframes are not supported in IE9 and earlier</h2>
<div class="box">
<div class="top">top</div>
<div class="caret"><i class="fa fa-caret-square-o-up"></i>
</div>
<div class="bottom">bottom</div>
</div>
<p>
<button id="btnf">SPIN CLOCKWISE</button>
</p>
<p>
<button id="btnb">SPIN COUTNER CLOCKWISE</button>
</p>
I need to create a rotation animation. A click event spins an element 180° to point down. Another click event spins the same element back to 0° to point up.
I have animation-fill-mode
to set to forwards
to preserve the last keyframe state. But it does not appear to be working. All visual elements reset to the default state.
Any ideas what I may be doing wrong?
My Codepen: http://codepen.io/simspace-dev/pen/RrpGmP
My code:
(function() {
$('#btnb').on('click', function(e) {
return $('.box').addClass('spin-counter-clockwise');
});
$('#btnf').on('click', function(e) {
return $('.box').addClass('spin-clockwise');
});
$('.box').on('webkitAnimationEnd', function(e) {
return $(e.target).removeClass('spin-counter-clockwise').removeClass('spin-clockwise');
});
}.call(this));
.box {
background: red;
position: relative;
width: 176px;
height: 176px;
margin: 40px auto;
text-align: center;
}
.box .top {
background: green;
position: absolute;
top: 0;
width: 100%;
height: 28px;
}
.box .bottom {
background: purple;
position: absolute;
bottom: 0;
width: 100%;
height: 28px;
}
.box .caret {
color: white;
font-size: 88px;
position: absolute;
top: 42px;
left: 50px;
}
.spin-clockwise {
-moz-animation: spin 2s;
-webkit-animation: spin 2s;
-moz-animation-fill-mode: forwards;
-webkit-animation-fill-mode: forwards;
}
.spin-counter-clockwise {
-moz-animation: spin 2s reverse;
-webkit-animation: spin 2s reverse;
-moz-animation-fill-mode: forwards;
-webkit-animation-fill-mode: forwards;
}
@keyframes spin {
from {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
to {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
}
body {
text-align: center;
margin: 0 auto;
}
<link href="https://maxcdn.bootstrapcdn./font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h2>Keyframes are not supported in IE9 and earlier</h2>
<div class="box">
<div class="top">top</div>
<div class="caret"><i class="fa fa-caret-square-o-up"></i>
</div>
<div class="bottom">bottom</div>
</div>
<p>
<button id="btnf">SPIN CLOCKWISE</button>
</p>
<p>
<button id="btnb">SPIN COUTNER CLOCKWISE</button>
</p>
Share
Improve this question
edited Jan 6, 2016 at 6:22
Harry
89.9k26 gold badges214 silver badges223 bronze badges
asked Jan 5, 2016 at 23:18
Chris SimeoneChris Simeone
1,2052 gold badges16 silver badges29 bronze badges
3
- Is there any specific reason why you've used animations? It would be much easier to achieve this with transitions instead of animation. – Harry Commented Jan 6, 2016 at 4:29
- 1 Thanks Harry, I will look into transitions. – Chris Simeone Commented Jan 6, 2016 at 6:23
- 1 Thanks for the great answers Harry, Chris and oMiKeY! If it turns out I use transitions (which sounds like the better method), I'm still glad I attempted this route for the learning experience. I never messed around with CSS animations prior to this and I learned much. – Chris Simeone Commented Jan 6, 2016 at 6:34
3 Answers
Reset to default 3TL;DR: (straight to the suggested solution)
If all you need is a rotation from 0° to 180° on the click of one button and back from 180° to 0° on the other then I would suggest using transitions instead of animations. Transitions by default produce the reverse effect and so there is no need to code for two different states (which makes it even better).
(function() {
$('#btnb').on('click', function(e) {
return $('.box').removeClass('spin');
});
$('#btnf').on('click', function(e) {
return $('.box').addClass('spin');
});
}.call(this));
.box {
background: red;
position: relative;
width: 176px;
height: 176px;
margin: 40px auto;
text-align: center;
transition: transform 1s linear;
/* add this to enable transition */
}
.box .top {
background: green;
position: absolute;
top: 0;
width: 100%;
height: 28px;
}
.box .bottom {
background: purple;
position: absolute;
bottom: 0;
width: 100%;
height: 28px;
}
.box .caret {
color: white;
font-size: 88px;
position: absolute;
top: 42px;
left: 50px;
}
.spin {
/* this is the only thing required for rotation (along with the JS) */
transform: rotate(180deg);
}
body {
text-align: center;
margin: 0 auto;
}
<link href="https://maxcdn.bootstrapcdn./font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h2>Keyframes are not supported in IE9 and earlier</h2>
<div class="box">
<div class="top">top</div>
<div class="caret"><i class="fa fa-caret-square-o-up"></i>
</div>
<div class="bottom">bottom</div>
</div>
<p>
<button id="btnf">SPIN CLOCKWISE</button>
</p>
<p>
<button id="btnb">SPIN COUTNER CLOCKWISE</button>
</p>
If you were using animations only for learning purpose, the details provided below should still be useful to you in terms of understanding how animations work, what are the limitations because of it etc.
Chris' answer touches upon the reason for your problem but I thought the question merited a bit more detailed explanation of two things - (1) Why the element doesn't hold the state as at the last keyframe even though animation-fill-mode: forwards
setting is applied (2) Why the same keyframe couldn't be used for the reverse animation (when the class with the original animation was not removed). I also wanted to suggest a different alternate to the whole thing and hence the separate answer.
Why does the element not hold the state as at the last keyframe even though fill mode is set to forwards?
This is because you are removing the class that adds the animation as soon as animation pletes (inside the on('webkitAnimationEnd')
event handler). Generally when animation-fill-mode
is set to forwards
, the UA uses the settings (or property-value pair) that are provided within last keyframe to maintain the state. But once the class is removed (and in-turn the animation settings), the UA does not keep track of (or know what) animations that were prior present on the element, their state and fill mode etc. Once animation is removed, the browser triggers a repaint and this will be performed based on classes that are present on the element as at the time of the repaint. Due to this, the element would snap back to its un-rotated state. You can read more about it in my answer here to a similar question (but not the same :)).
Why can't the same keyframe be used for the reverse animation (when the class which had the original animation was not removed)?
This again is because of how animations generally work. When any animation is added to an element, the UA maintains details about the animation's keyframes, its state etc as long as it is attached to the element. So, unless the class which added the forward (0° to 180°) animation is removed, the browser thinks that it has executed the animation to pletion (as default iteration count is just 1) and so even when a class with the reverse animation is added, it does nothing. The only way to make it restart the animation in reverse direction is by removing the class with the forward animation and then adding the class with the reverse animation. You can have a look at this answer also for related reading.
Because of the aforementioned reasons, the only way to achieve what you need with animations is to create two different animations (or keyframes) for the forward and reverse animations, set them under two different classes and keep changing the classes using JavaScript. This whole process bees tedious and is generally not necessary when all you need is a rotation from (0° to 180°) on the click of one button and back from (180° to 0°) on the other. This whole thing can be achieved using transitions and what makes this even better is the fact that transitions by default produce the reverse effect and so there is no need to code for two different states.
Further Reading:
What are the differences between Transitions and Animations
Choosing Transitions or Animations - When to use which?
If the need is to have continuous clockwise or counter-clockwise rotations with each button click (like in oMiKeY's answer) then I'd still remend using transition with a bit of JS like in the below snippet. Let's leave animations for more plex stuff (and in specific stuff that'd happen without any triggers).
(function() {
var deg = 0;
$('#btnb').on('click', function(e) {
deg -= 180;
return $('.box').css('transform', 'rotate(' + deg + 'deg)');
});
$('#btnf').on('click', function(e) {
deg += 180;
return $('.box').css('transform', 'rotate(' + deg + 'deg)');
});
}.call(this));
.box {
background: red;
position: relative;
width: 176px;
height: 176px;
margin: 40px auto;
text-align: center;
transition: transform 1s linear; /* add this to enable transition */
}
.box .top {
background: green;
position: absolute;
top: 0;
width: 100%;
height: 28px;
}
.box .bottom {
background: purple;
position: absolute;
bottom: 0;
width: 100%;
height: 28px;
}
.box .caret {
color: white;
font-size: 88px;
position: absolute;
top: 42px;
left: 50px;
}
body {
text-align: center;
margin: 0 auto;
}
<link href="https://maxcdn.bootstrapcdn./font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h2>Keyframes are not supported in IE9 and earlier</h2>
<div class="box">
<div class="top">top</div>
<div class="caret"><i class="fa fa-caret-square-o-up"></i>
</div>
<div class="bottom">bottom</div>
</div>
<p>
<button id="btnf">SPIN CLOCKWISE</button>
</p>
<p>
<button id="btnb">SPIN COUTNER CLOCKWISE</button>
</p>
So the root issue was the class with the animation was being removed.
I couldn't get it to work using the same keyframes, but what i did was create a new keyframes for counter clockwise, and then removed the opposite class when the buttons were clicked
Changes:
css
.spin-clockwise {
-moz-animation: spin 2s;
-webkit-animation: spin 2s;
}
.spin-fill-mode {
-moz-animation-fill-mode: forwards;
-webkit-animation-fill-mode: forwards;
animation-fill-mode: forwards;
}
.spin-counter-clockwise {
-moz-animation: spin-counter 2s;
-webkit-animation: spin-counter 2s;
}
@keyframes spin {
from {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
to {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
}
@keyframes spin-counter {
from {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
to {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
}
js:
$('#btnb').on('click', (e)->
$('.box')
.addClass('spin-counter-clockwise')
.removeClass('spin-clockwise')
)
$('#btnf').on('click', (e) ->
$('.box')
.addClass('spin-clockwise')
.removeClass('spin-counter-clockwise')
)
And add the class spin-fill-mode to box. Though you could probably just leave the fill-mode in the animation classes... updated codepen:
http://codepen.io/anon/pen/QypvOr
I fiddled with it for a while then decided you might need two separate rotation animations.
Check out my fiddle: http://codepen.io/anon/pen/jWBmZK
(function() {
$('#btnb').on('click', function(e) {
return $('.box')
.addClass('spin-counter-clockwise')
.toggleClass('upside-down');
});
$('#btnf').on('click', function(e) {
return $('.box')
.addClass('spin-clockwise')
.toggleClass('upside-down');
});
$('.box').on('webkitAnimationEnd', function(e) {
return $(e.target).removeClass('spin-counter-clockwise').removeClass('spin-clockwise');
});
}.call(this));
.box {
background: red;
position: relative;
width: 176px;
height: 176px;
margin: 40px auto;
text-align: center;
}
.box .top {
background: green;
position: absolute;
top: 0;
width: 100%;
height: 28px;
}
.box .bottom {
background: purple;
position: absolute;
bottom: 0;
width: 100%;
height: 28px;
}
.box .caret {
color: white;
font-size: 88px;
position: absolute;
top: 42px;
left: 50px;
}
.upside-down {
-moz-transform: rotate(180deg);
-webkit-transform: rotate(180deg);
-ms-transform: rotate(180deg);
-o-transform: rotate(180deg);
transform: rotate(180deg);
}
.spin-clockwise.upside-down {
-moz-animation: spin 2s;
-webkit-animation: spin 2s;
-moz-animation-fill-mode: forwards;
-webkit-animation-fill-mode: forwards;
}
.spin-counter-clockwise {
-moz-animation: spin 2s reverse;
-webkit-animation: spin 2s reverse;
-moz-animation-fill-mode: forwards;
-webkit-animation-fill-mode: forwards;
}
.spin-clockwise {
-moz-animation: back-spin 2s;
-webkit-animation: back-spin 2s;
-moz-animation-fill-mode: forwards;
-webkit-animation-fill-mode: forwards;
}
.spin-counter-clockwise.upside-down {
-moz-animation: back-spin 2s reverse;
-webkit-animation: back-spin 2s reverse;
-moz-animation-fill-mode: forwards;
-webkit-animation-fill-mode: forwards;
}
@keyframes spin {
from {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
to {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
}
@keyframes back-spin {
from {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
to {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
body {
text-align: center;
margin: 0 auto;
}
<link href="https://maxcdn.bootstrapcdn./font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<body>
<h2>Keyframes are not supported in IE9 and earlier</h2>
<div class="box">
<div class="top">top</div>
<div class="caret"><i class="fa fa-caret-square-o-up"></i>
</div>
<div class="bottom">bottom</div>
</div>
<p>
<button id="btnf">SPIN CLOCKWISE</button>
</p>
<p>
<button id="btnb">SPIN COUTNER CLOCKWISE</button>
</p>
</body>
</html>
本文标签: javascriptCSS Animation Fill ModeWhat have I done wrongStack Overflow
版权声明:本文标题:javascript - CSS Animation Fill Mode - What have I done wrong? - Stack Overflow 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://it.en369.cn/questions/1745618676a2159443.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论