CSS动画填充模式 - 我做错了什么?

时间:2022-03-18 06:15:57

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.

我需要创建一个旋转动画。单击事件将元素旋转180°以指向下方。另一个单击事件将相同的元素旋转回0°以指向上方。

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

我的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.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/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>

3 个解决方案

#1


2  

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:

并将类spin-fill-mode添加到框中。虽然您可能只是将填充模式留在动画类中...更新了代码集:

http://codepen.io/anon/pen/QypvOr

#2


3  

TL;DR: (straight to the suggested solution)

TL; DR :(直接建议的解决方案)

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).

如果您只需要点击一个按钮从0°旋转到180°,然后从另一个按钮旋转180°到0°,那么我建议使用过渡而不是动画。默认情况下,转换产生相反的效果,因此不需要为两种不同的状态编码(这使得它更好)。

(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.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/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.

克里斯的回答触及了你的问题的原因,但我认为这个问题值得更详细地解释两件事 - (1)为什么元素不像最后一个关键帧那样保持状态,即使动画填充模式:应用转发设置(2)为什么相同的关键帧不能用于反向动画(当未删除具有原始动画的类时)。我还想建议一个不同的替代整个事情,因此单独的答案。

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 completes (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 :)).

这是因为您在动画完成后立即删除添加动画的类(在on('webkitAnimationEnd')事件处理程序内)。通常,当动画填充模式设置为向前时,UA使用在最后一个关键帧内提供的设置(或属性 - 值对)来维持状态。但是一旦类被移除(并且反过来动画设置),UA就不会跟踪(或知道什么)元素上先前存在的动画,它们的状态和填充模式等。一旦动画被移除,浏览器触发重绘,这将根据重绘时元素上存在的类执行。因此,元件将弹回到其未旋转状态。您可以在我的答案中阅读更多相关问题(但不一样:))。

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 completion (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.

这也是因为动画通常如何工作。当任何动画添加到元素时,UA会保留有关动画关键帧,其状态等的详细信息,只要它附加到元素即可。因此,除非删除添加了前进(0°到180°)动画的类,否则浏览器会认为它已完成动画(默认迭代计数仅为1),因此即使是具有反向动画的类也是如此添加,它什么都不做。使其以反向方向重新启动动画的唯一方法是使用前向动画删除类,然后使用反向动画添加类。您也可以查看相关阅读的答案。

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 becomes 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.

由于上述原因,使用动画实现所需内容的唯一方法是为正向和反向动画创建两个不同的动画(或关键帧),将它们设置在两个不同的类下,并使用JavaScript继续更改类。整个过程变得单调乏味,当你需要的是从一个按钮的单击旋转(0°到180°)到另一个按钮的旋转(180°到0°)时,通常不需要。使用转换可以实现这一切,并且更好的是,默认情况下转换会产生相反的效果,因此不需要为两个不同的状态进行编码。

Further Reading:


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 recommend using transition with a bit of JS like in the below snippet. Let's leave animations for more complex stuff (and in specific stuff that'd happen without any triggers).

如果需要按下每个按钮进行连续的顺时针或逆时针旋转(就像在oMiKeY的回答中那样),那么我仍然建议使用带有一点JS的过渡,如下面的代码片段所示。让我们为更复杂的东西(以及没有任何触发器的特定事物)留下动画。

(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.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/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>

#3


1  

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

看看我的小提琴: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.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/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>

#1


2  

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:

并将类spin-fill-mode添加到框中。虽然您可能只是将填充模式留在动画类中...更新了代码集:

http://codepen.io/anon/pen/QypvOr

#2


3  

TL;DR: (straight to the suggested solution)

TL; DR :(直接建议的解决方案)

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).

如果您只需要点击一个按钮从0°旋转到180°,然后从另一个按钮旋转180°到0°,那么我建议使用过渡而不是动画。默认情况下,转换产生相反的效果,因此不需要为两种不同的状态编码(这使得它更好)。

(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.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/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.

克里斯的回答触及了你的问题的原因,但我认为这个问题值得更详细地解释两件事 - (1)为什么元素不像最后一个关键帧那样保持状态,即使动画填充模式:应用转发设置(2)为什么相同的关键帧不能用于反向动画(当未删除具有原始动画的类时)。我还想建议一个不同的替代整个事情,因此单独的答案。

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 completes (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 :)).

这是因为您在动画完成后立即删除添加动画的类(在on('webkitAnimationEnd')事件处理程序内)。通常,当动画填充模式设置为向前时,UA使用在最后一个关键帧内提供的设置(或属性 - 值对)来维持状态。但是一旦类被移除(并且反过来动画设置),UA就不会跟踪(或知道什么)元素上先前存在的动画,它们的状态和填充模式等。一旦动画被移除,浏览器触发重绘,这将根据重绘时元素上存在的类执行。因此,元件将弹回到其未旋转状态。您可以在我的答案中阅读更多相关问题(但不一样:))。

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 completion (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.

这也是因为动画通常如何工作。当任何动画添加到元素时,UA会保留有关动画关键帧,其状态等的详细信息,只要它附加到元素即可。因此,除非删除添加了前进(0°到180°)动画的类,否则浏览器会认为它已完成动画(默认迭代计数仅为1),因此即使是具有反向动画的类也是如此添加,它什么都不做。使其以反向方向重新启动动画的唯一方法是使用前向动画删除类,然后使用反向动画添加类。您也可以查看相关阅读的答案。

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 becomes 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.

由于上述原因,使用动画实现所需内容的唯一方法是为正向和反向动画创建两个不同的动画(或关键帧),将它们设置在两个不同的类下,并使用JavaScript继续更改类。整个过程变得单调乏味,当你需要的是从一个按钮的单击旋转(0°到180°)到另一个按钮的旋转(180°到0°)时,通常不需要。使用转换可以实现这一切,并且更好的是,默认情况下转换会产生相反的效果,因此不需要为两个不同的状态进行编码。

Further Reading:


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 recommend using transition with a bit of JS like in the below snippet. Let's leave animations for more complex stuff (and in specific stuff that'd happen without any triggers).

如果需要按下每个按钮进行连续的顺时针或逆时针旋转(就像在oMiKeY的回答中那样),那么我仍然建议使用带有一点JS的过渡,如下面的代码片段所示。让我们为更复杂的东西(以及没有任何触发器的特定事物)留下动画。

(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.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/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>

#3


1  

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

看看我的小提琴: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.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/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>