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

时间:2016-01-05 23:18:33

标签: javascript jquery css css3 css-animations

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

我将animation-fill-mode设置为forwards以保留最后一个关键帧状态。但它似乎没有起作用。所有可视元素都重置为默认状态。

任何想法我可能做错了什么?

我的Codepen http://codepen.io/simspace-dev/pen/RrpGmP

我的代码

(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 个答案:

答案 0 :(得分:3)

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

如果您需要的是在单击一个按钮时从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>

如果您仅将动画用于学习目的,则在理解动画如何工作,由此产生的限制等方面,下面提供的详细信息对您仍然有用。

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

为什么元素不能保持最后一个关键帧的状态,即使填充模式设置为向前?

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

为什么不能将相同的关键帧用于反向动画(当没有删除原始动画的类时)?

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

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

进一步阅读:

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

forwards
(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;
}

答案 1 :(得分:2)

因此根本问题是正在删除动画的类。

我无法使用相同的关键帧使用它,但我所做的是为逆时针创建一个新的关键帧,然后在单击按钮时删除相反的类

的变化:

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

并将类spin-fill-mode添加到框中。虽然你可能只是将填充模式留在动画类中...... 更新的codepen:

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

答案 2 :(得分:1)

我摆弄它一段时间然后决定你可能需要两个单独的旋转动画。

查看我的小提琴: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>