代码之家  ›  专栏  ›  技术社区  ›  Jeanluca Scaljeri

单击后来回运行css动画

  •  8
  • Jeanluca Scaljeri  · 技术社区  · 6 年前

    使用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 但没有播放动画。动画最初不应该播放(我遇到过几次)。有什么建议我可以做到这一点吗?

    3 回复  |  直到 6 年前
        1
  •  8
  •   Temani Afif BoltClock    6 年前

    我会考虑使用 animation-play-state 属性和用途 infinite alternate 。其想法是运行动画并在动画结束时停止,然后再次运行,依此类推:

    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>
        2
  •  3
  •   vals    6 年前

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

    对于您的情况,我建议将其更改为单一过渡。在这种情况下,浏览器可以更好地处理开/关部件。要通过过渡实现背景色的双重更改,请使用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>
        3
  •  0
  •   Frank N dqthe    4 年前

    好的,这是我的方法:

    • 保持动画,直到添加动画 .enabled (防止加载动画)
    • 切换 .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>