首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >反转CSS动画

反转CSS动画
EN

Stack Overflow用户
提问于 2016-02-20 16:38:28
回答 3查看 4.8K关注 0票数 3

我做了这个:http://codepen.io/yayoni/pen/pgXoWY

当我点击小按钮时,我想逆转动画,但是我所做的不工作,我不明白为什么。

代码语言:javascript
复制
function anim() {
  var div = document.getElementById('fab');
  div.className = "anim";
}

function animrev() {
  var div = document.getElementById('fab');
  div.className = "animrev";
}
代码语言:javascript
复制
html,
body {
  height: 100%;
  width: 100%;
}
#content {
  height: 100%;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}
#fab {
  margin-right: 30px;
  color: white;
  font-size: 45px;
  outline: 0;
  border: 0;
  height: 150px;
  width: 150px;
  border-radius: 75px;
  text-align: center;
  background-color: red;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
}
.anim {
  animation-name: example;
  animation-duration: 1s;
  animation-fill-mode: forwards;
}
@keyframes example {
  100% {
    background-color: green;
    left: 0px;
    top: 0px;
  }
}
@keyframes exampleux {
  100% {
    background-color: red;
    left: 0px;
    top: 0px;
  }
}
.animrev {
  animation-name: exampleux;
  animation-duration: 1s;
  animation-fill-mode: forwards;
}
代码语言:javascript
复制
<div id="content">
  <button onclick="anim()" id="fab">+</button>
  <button onclick="animrev()" id="fab2">+</button>
</div>

有关更多细节,请参见CodePen

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-02-21 07:14:05

如果这是一个简单的颜色变化,我也会推荐CSS转换,比如在马丁的回答中,但是正如您已经解释过的,它是更复杂的东西,Osama8DZ的答复是您最好的解决方案。但这并没有给出你的问题的答案,你的问题说明如下(重点是我的):

当我点击小按钮时,我想反转动画,但是我所做的不工作,,我不明白为什么

原因:

当您单击导致反向动画触发的按钮时,类名会更改,因此原始动画将被反向动画替换。这实际上是两个步骤-第一是删除原来的动画,第二是添加反向。

每当删除存在于元素上的动画时,该元素立即切换到其原始状态(即动画之前的状态)。在这里,元素的原始状态为红色背景。因此,元素立即获得一个红色背景,然后反向动画没有视觉效果,因为它是动画从红色背景到红色背景

您可以在下面的片段中看到我所指的示例。我在元素的原始状态中添加了左和上边距,并在前向动画中更改了它。当执行反向按钮单击时,形状立即返回原始状态,然后应用反向动画中提供的左边、顶部边距。

代码语言:javascript
复制
var div = document.getElementById('fab');

function anim() {
  div.className = "anim";
}

function animrev() {
  div.className = "animrev";
}
代码语言:javascript
复制
html,
body {
  height: 100%;
  width: 100%;
}
#content {
  height: 100%;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}
#fab {
  margin-right: 30px;
  color: white;
  font-size: 45px;
  outline: 0;
  border: 0;
  height: 150px;
  width: 150px;
  border-radius: 75px;
  text-align: center;
  background-color: red;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
  
  /* added these for demo */
  margin-left: 20px;
  margin-top: 10px;
}
.anim {
  animation-name: example;
  animation-duration: 1s;
  animation-fill-mode: forwards;
}
@keyframes example {
  100% {
    background-color: green;
    left: 0px;
    top: 0px;
    
    /* added these for demo */
    margin-left: 40px;
    margin-top: 20px;
  }
}
@keyframes exampleux {
  100% {
    background-color: red;
    left: 0px;
    top: 0px;

    /* added these for demo */
    margin-left: 30px;
    margin-top: 15px;    
  }
}
.animrev {
  animation-name: exampleux;
  animation-duration: 1s;
  animation-fill-mode: forwards;
}
代码语言:javascript
复制
<div id="content">
  <button onclick="anim()" id="fab">+</button>
  <button onclick="animrev()" id="fab2">+</button>
</div>

解决方案:

简单和最好的解决方案将是Osama8DZ的答复中提供的解决方案,因为它使原始元素看起来似乎从未恢复到原来的状态。我不会再详细说明这一点,因为这看起来像是在抄袭他的答案(或)剽窃。

但是,我将重点介绍几个不起作用的案例,以及如何解决这些问题。

案例1:当动画有延迟时-当动画(或)都被延迟时,您仍然能够看到它在运行动画之前快速恢复到原始状态。下面的片段显示了实际操作中的问题。

代码语言:javascript
复制
var div = document.getElementById('fab');

function anim() {
  div.className = "anim";
}

function animrev() {
  div.className = "animrev";
}
代码语言:javascript
复制
html,
body {
  height: 100%;
  width: 100%;
}
#content {
  height: 100%;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}
#fab {
  margin-right: 30px;
  color: white;
  font-size: 45px;
  outline: 0;
  border: 0;
  height: 150px;
  width: 150px;
  border-radius: 75px;
  text-align: center;
  background-color: red;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
}
.anim {
  animation-name: example;
  animation-duration: 1s;
  animation-fill-mode: forwards;
  animation-delay: 1s;
}
@keyframes example {
  100% {
    background-color: green;
    left: 0px;
    top: 0px;
  }
}
@keyframes exampleux {
  0% {
    /* You need to add this */
    background-color: green;
    left: 0px;
    top: 0px;  
  }
  100% {
    background-color: red;
    left: 0px;
    top: 0px;
  }
}
.animrev {
  animation-name: exampleux;
  animation-duration: 1s;
  animation-fill-mode: forwards;
  animation-delay: 1s;
}
代码语言:javascript
复制
<div id="content">
  <button onclick="anim()" id="fab">+</button>
  <button onclick="animrev()" id="fab2">+</button>
</div>

如何修复它?原因是因为动画将继续保持其原始状态,直到延迟时间过去,因此即使反向动画中的0%关键帧与前向动画的100%关键帧相同,元素仍然会快速恢复,然后再动画。修复方法是将animation-fill-mode设置为both (这意味着,具有forwardsbackwards的效果),而不是forwards。这使得元素在延迟期间(由于0% )保持状态与在100%关键帧中的状态相同,并且在动画结束后(由于forwards)仍保持状态为100%关键帧。

代码语言:javascript
复制
var div = document.getElementById('fab');

function anim() {
  div.className = "anim";
}

function animrev() {
  div.className = "animrev";
}
代码语言:javascript
复制
html,
body {
  height: 100%;
  width: 100%;
}
#content {
  height: 100%;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}
#fab {
  margin-right: 30px;
  color: white;
  font-size: 45px;
  outline: 0;
  border: 0;
  height: 150px;
  width: 150px;
  border-radius: 75px;
  text-align: center;
  background-color: red;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
}
.anim {
  animation-name: example;
  animation-duration: 1s;
  animation-fill-mode: both;
  animation-delay: 1s;
}
@keyframes example {
  100% {
    background-color: green;
    left: 0px;
    top: 0px;
  }
}
@keyframes exampleux {
  0% {
    /* You need to add this */
    background-color: green;
    left: 0px;
    top: 0px;  
  }
  100% {
    background-color: red;
    left: 0px;
    top: 0px;
  }
}
.animrev {
  animation-name: exampleux;
  animation-duration: 1s;
  animation-fill-mode: both;
  animation-delay: 1s;
}
代码语言:javascript
复制
<div id="content">
  <button onclick="anim()" id="fab">+</button>
  <button onclick="animrev()" id="fab2">+</button>
</div>

案例2:,如果反向动画对于多个元素是常见的,但是前向动画是不同的,就像下面的片段所示。在下面的片段中,第一个元素的前向动画将背景从red更改为green,而第二个元素将其从red更改为blue,但反向动画应该将两者都设置为red。在这种情况下,我们不能将反向动画的0%关键帧设置为前向动画的100%,因为对于这两个前向动画,结束状态是不同的。

代码语言:javascript
复制
var div = document.getElementById('fab');
var div2 = document.getElementById('fab3');

function anim() {
  div.className = "anim";
}
function animAlt() {  
  div2.className = "anim-alt";
}

function animrev() {
  div.className = "animrev";
  div2.className = "animrev";
}
代码语言:javascript
复制
html,
body {
  height: 100%;
  width: 100%;
}
#content {
  height: 100%;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}
#fab, #fab3 {
  margin-right: 30px;
  color: white;
  font-size: 45px;
  outline: 0;
  border: 0;
  height: 150px;
  width: 150px;
  border-radius: 75px;
  text-align: center;
  background-color: red;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
}
.anim {
  animation-name: example;
  animation-duration: 1s;
  animation-fill-mode: forwards;
}
@keyframes example {
  100% {
    background-color: green;
    left: 0px;
    top: 0px;
  }
}
.anim-alt {
  animation-name: example2;
  animation-duration: 1s;
  animation-fill-mode: forwards;
}
@keyframes example2 {
  100% {
    background-color: blue;
    left: 0px;
    top: 0px;
  }
}

@keyframes exampleux {
  0% {
    /* You need to add this */
    background-color: green;
    left: 0px;
    top: 0px;  
  }
  100% {
    background-color: red;
    left: 0px;
    top: 0px;
  }
}
.animrev {
  animation-name: exampleux;
  animation-duration: 1s;
  animation-fill-mode: forwards;  
}
代码语言:javascript
复制
<div id="content">
  <button onclick="anim()" id="fab">+</button>
  <button onclick="animAlt()" id="fab3">+</button>
  <button onclick="animrev()" id="fab2">+</button>
</div>

如何修复?在这种情况下没有纯粹的CSS解决方案(除非您切换到使用转换)。不过,有一个解决办法,就是在元素结束后,通过内联样式将原始动画的最后一个关键帧中的样式添加到元素中。这意味着我们在模仿元素的效果,而不是突然恢复到它原来的状态。

代码语言:javascript
复制
var div = document.getElementById('fab');
var div2 = document.getElementById('fab3');

function anim() {
  div.className = "anim";
}
function animAlt() {
  div2.className = "anim-alt";
}

function animrev() {
  div.className = "animrev";
  div2.className = "animrev";
}

div.addEventListener('animationend', function(e) {
  if (e.animationName == "example") { /* meaning the forward animation has ended */
    this.style.backgroundColor = 'green';
    this.style.marginLeft = '40px';
    this.style.marginTop = '20px';
  }
  else
    this.style = null;
})
div2.addEventListener('animationend', function(e) {
  if (e.animationName == "example2") { /* meaning the forward animation has ended */
    this.style.backgroundColor = 'blue';
    this.style.marginLeft = '40px';
    this.style.marginTop = '20px';
  }  
  else
    this.style = null;
})
代码语言:javascript
复制
html,
body {
  height: 100%;
  width: 100%;
}
#content {
  height: 100%;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}
#fab, #fab3 {
  margin-right: 30px;
  color: white;
  font-size: 45px;
  outline: 0;
  border: 0;
  height: 150px;
  width: 150px;
  border-radius: 75px;
  text-align: center;
  background-color: red;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
  
  margin-left: 20px;
  margin-top: 10px;  
}
.anim {
  animation-name: example;
  animation-duration: 1s;
  animation-fill-mode: forwards;
}
@keyframes example {
  100% {
    background-color: green;
    left: 0px;
    top: 0px;
    
    margin-left: 40px;
    margin-top: 20px;    
  }
}
.anim-alt {
  animation-name: example2;
  animation-duration: 1s;
  animation-fill-mode: forwards;
}
@keyframes example2 {
  100% {
    background-color: blue;
    left: 0px;
    top: 0px;
    
    margin-left: 40px;
    margin-top: 20px;
  }
}

@keyframes exampleux {
  100% {
    background-color: red;
    left: 0px;
    top: 0px;
    
    margin-left: 20px;
    margin-top: 10px;
  }
}
.animrev {
  animation-name: exampleux;
  animation-duration: 1s;
  animation-fill-mode: forwards;  
}
代码语言:javascript
复制
<div id="content">
  <button onclick="anim()" id="fab">+</button>
  <button onclick="animAlt()" id="fab3">+</button>
  <button onclick="animrev()" id="fab2">+</button>
</div>

注意:我们不应该将内联样式保留为-,因为这会导致第二次单击原始动画时出现问题。因此,我们必须监听动画的end事件,并删除内联样式(如果有的话)。animationend仍然需要几个版本的浏览器前缀,但是我会把这部分留给您。

我希望上面的所有内容都为您提供了一个完整的解释,说明为什么您的代码(似乎)不能工作,以及如何修复各种场景。

票数 4
EN

Stack Overflow用户

发布于 2016-02-20 16:51:45

事实上,您不需要使用任何CSS3关键帧或动画,只使用transition: background-color 1s linear;来创建颜色转换。

见您更新的演示:http://codepen.io/anon/pen/YwozaQ

票数 0
EN

Stack Overflow用户

发布于 2016-02-20 18:09:19

尝试:

代码语言:javascript
复制
@keyframes exampleux {
0%   
{
    background-color: green; left:0px; top:0px; /* You need to add this */
}

100% 
{
    background-color: red; left:0px; top:0px;
}
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35525992

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档