【问题标题】:Run css animation back and forth on clicks在点击时来回运行 css 动画
【发布时间】:2018-09-09 13:50:24
【问题描述】:

使用 css @keyframes 我试图在单击元素时将一些动画附加到元素上。

.animate {
    animation-name: action;
    animation-duration: 2s;
    animation-timing-function: linear;
    background-color: green;
} 

@keyframes action {
    0% {
        background-color: gray; 
    }  

   50% {
       background-color: red;
   }

   100% {
       background-color: green;
   }
}

DEMO

.animate 类在单击时添加,并且该框从灰色变为绿色。但是现在我想再次单击它时将动画恢复为灰色(切换功能)。我尝试使用animation-direction: reverse 使用相同的动画,但没有播放动画。动画最初不应该播放(我遇到过几次)。有什么建议可以实现吗?

【问题讨论】:

  • 我认为你应该制作另一个动画来反转它。例如,您有两个类 .animte-gray 和 .animate-green。并使用 javascript 切换类。希望它有效
  • 是的,这似乎是一个简单的解决方案:demo

标签: css css-animations keyframe


【解决方案1】:

好的,这是我的方法:

  • 保持动画,直到你添加了.enabled(防止加载动画)
  • 在每次点击时切换 .active
  • 重要:.active中定义一个→不同的←动画,即使你前后摇晃或摆动的动画是相同的,也将其定义为副本。 (否则回来的路上会有没有动画)

const div = document.querySelector('.target')
div.addEventListener('click', (e) => {
  div.classList.add('active');
  div.classList.toggle('play');
})
/* REF https://stackoverflow.com/a/49575979 */
body, html { /* eye candy */
  background: #444; display: flex; min-height: 100vh; align-items: center; justify-content: center;
}

div { /* eye candy */
  width: 200px; height: 100px; border: 12px dashed #888; border-radius: 20px; 
  background: red;
}

/* prevents that there is an animation already on loading */
.active {
  animation: trafficLight 2s linear;
}

.play {
  border: 12px solid white; /* white border == play */
  background: green;
  /* yes, already setting for the way back!
     fun fact: if you do not set a DIFFERENT animation, NO animation whatsoever will happen
    (so also for simple bounce animations, where forth=back would be o.k.
     you do need to clone it... varying time (1.001s) or direction is NOT enough.) */
  animation: trafficLightBack 2s linear;
}

@keyframes trafficLight {
  0% { background-color: green; }  
  50% { background-color: yellow; }  
  100% { background-color: red;}  
}

@keyframes trafficLightBack {
  0% { background-color: red; }  
  50% { background-color: yellow; }  
  100% { background-color: green;}  
}
<div class="target"></div>

【讨论】:

    【解决方案2】:

    用动画处理这种开/关变化总是很棘手,而且很难平滑无缝地处理重复的变化。

    对于您的情况,我建议将其更改为单个过渡。在这种情况下,浏览器可以更好地处理开/关部分。要通过过渡实现背景颜色的双重变化,请创建 3 种颜色的渐变,并更改渐变位置:

    const div = document.querySelector('.test')
    div.addEventListener('click', (e) => {
       div.classList.toggle('play');
    })
    .test {
      border: solid 1px black;
      margin: 10px;
      height: 100px;
      width: 100px;
      background-image: linear-gradient(gray 0%, gray 20%, blue 40%, blue 60%,
       red 80%, red 100%);
      background-size: 100% 9000%;
      background-repeat: no-repeat;
      background-position: center top;
      transition: background-position .3s;
    }
    
    .play {
      background-position: center bottom;
    }
    <div class="test">
    </div>

    【讨论】:

    • 我喜欢这个想法,即使使用大的 background-size 值有点 hacky
    • 我注意到如果持续时间更快,比如 0.3 秒,javascript 代码会与 css 动画有点不同步。你知道让它们保持同步的方法吗?
    • @JeanlucaScaljeri 我已按照您的建议将时间更改为 .3 秒,但我看不到不同步的效果。您能否进一步解释一下您看到的效果是什么?
    • @TemaniAfif 比你的编辑!大背景尺寸只是为了避免结果出现条带。但是用更小的尺寸来做这也是一个很酷的效果
    • 对不起,我搞砸了,评论是针对下面的帖子的。非常感谢您的解决方案!
    【解决方案3】:

    我会考虑使用animation-play-state 属性并同时使用infinitealternate。这个想法是运行动画并在结束时停止它,然后再次运行它,依此类推:

    const div = document.querySelector('.target')
    div.addEventListener('click', (e) => {
       div.classList.add('play');
       setTimeout(function() {
          div.classList.remove('play');
       },2000)
    })
    .target {
      width: 100px;
      height: 100px;
      background-color: gray;
      cursor: pointer;
      animation: action 2s linear alternate infinite;
      animation-play-state:paused;
    }
    .play {
      animation-play-state:running;
    }
    
    @keyframes action {
      0% {
        background-color: gray; 
      }  
    
      50% {
        background-color: red;
      }
    
      100% {
         background-color: green;
      }
    }
    <div class="target">
    
    </div>

    【讨论】:

    • @JeanlucaScaljeri 只考虑一个动画,在这种情况下,当你减少时间时会很困难......也许解决方案是复制动画
    猜你喜欢
    • 1970-01-01
    • 2019-10-20
    • 1970-01-01
    • 2022-01-20
    • 2015-09-15
    • 1970-01-01
    • 1970-01-01
    • 2016-08-27
    • 2021-12-12
    相关资源
    最近更新 更多