【问题标题】:How do I change animation-timing-function during the animation?如何在动画期间更改动画计时功能?
【发布时间】:2020-02-28 20:01:09
【问题描述】:

我有动画,我希望元素(文本)在动画中间用ease-out 滚动并用ease-in 滚动。

所以基本上我想在动画中间更改animation-timing-function - 我如何在没有额外JS的情况下最好地实现这一点?

我考虑过 2 个连续的动画,但也许有更简单的方法?

var animatingNow = false;

function toggleRolling() {
  if (animatingNow) {
    return;
  }
  animatingNow = true;
  document.querySelector('.roller').classList.add('rolling');
  setTimeout(function() {
    animating = false;
    document.querySelector('.roller').classList.remove('rolling')
  }, 2120);

}
* {
  box-sizing: border-box;
}

body {
  font-family: 'Open Sans';
  font-size: 14px;
  padding: 30px 20px;
}

.wrapper {
  overflow: hidden;
  width: 100%;
  height: 40px;
  background: #444;
  border-radius: 5px;
  position: relative;
}

.wrapper .roller {
  position: absolute;
  right: 0;
  top: 0;
  height: 500%;
  display: flex;
  padding-right: 16px;
  flex-direction: column;
  user-select: none;
  color: white;
  opacity: 0.7;
  justify-content: space-between;
  transition: opacity 0.4s;
}

.wrapper .roller:hover,
.wrapper .roller.rolling {
  opacity: 1;
  --last-step-opacity: 0.7;
}

.wrapper .roller:hover {
  --last-step-opacity: 1;
}

.wrapper .roller.rolling {
  animation: roll 2.12s ease-out;
}

.wrapper .roller>span {
  height: 20%;
  display: flex;
  justify-content: flex-end;
  align-items: center;
}

@keyframes roll {
  0% {
    transform: translateY(0);
    opacity: 1;
  }
  10% {
    transform: translateY(0);
    opacity: 0;
  }
  11% {
    transform: translateY(-20%);
    opacity: 0;
  }
  12% {
    opacity: 1;
  }
  30%,
  70% {
    transform: translateY(-40%);
    opacity: 1;
  }
  88% {
    transform: translateY(-60%);
    opacity: 1;
  }
  89% {
    opacity: 0;
  }
  90% {
    transform: translateY(-80%);
  }
  100% {
    opacity: 0.7;
    opacity: var(--last-step-opacity);
    transform: translateY(-80%);
  }
}
<link href="https://fonts.googleapis.com/css?family=Open+Sans&display=swap" rel="stylesheet">
<div onclick="toggleRolling()" class="wrapper">
  <div class="roller">
    <span> <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" > <path fill-rule="evenodd" clip-rule="evenodd" d="M12 12H14C15.1046 12 16 11.1046 16 10V2C16 0.895431 15.1046 0 14 0H6C4.89543 0 4 0.895431 4 2V4H2C0.895431 4 0 4.89543 0 6V14C0 15.1046 0.895431 16 2 16H10C11.1046 16 12 15.1046 12 14V12ZM14 2H6V4H10C11.1046 4 12 4.89543 12 6V10H14V2ZM10 6H2L2 14H10V6Z" fill="currentColor" /> </svg></span>
    <span>Copied!</span>
    <span> <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" > <path fill-rule="evenodd" clip-rule="evenodd" d="M12 12H14C15.1046 12 16 11.1046 16 10V2C16 0.895431 15.1046 0 14 0H6C4.89543 0 4 0.895431 4 2V4H2C0.895431 4 0 4.89543 0 6V14C0 15.1046 0.895431 16 2 16H10C11.1046 16 12 15.1046 12 14V12ZM14 2H6V4H10C11.1046 4 12 4.89543 12 6V10H14V2ZM10 6H2L2 14H10V6Z" fill="currentColor" /> </svg></span>
  </div>
</div>

【问题讨论】:

    标签: javascript css css-animations css-transitions


    【解决方案1】:

    您可以不使用animation 来解决它,但使用 2 个不同的类:.rolling-in.rolling-out。此外,只有 1 个图标。然后,会有转入和转出的过渡。

    function toggleRolling(el) {
      el.classList.add('rolling-in');
      setTimeout(function(){
        el.classList.add('rolling-out')
      },1000)
      setTimeout(function(){
        el.classList.remove('rolling-in', 'rolling-out')
      },2000)
    }
    * {
      box-sizing: border-box;
    }
    
    body {
      font-family: 'Open Sans';
      font-size: 14px;
      padding: 30px 20px;
    }
    
    .wrapper {
      overflow: hidden;
      width: 100%;
      height: 40px;
      background: #444;
      border-radius: 5px;
      position: relative;
    }
    
    .wrapper .roller {
      position: absolute;
      right: 0;
      top: 0;
      height: 500%;
      display: flex;
      padding-right: 16px;
      flex-direction: column;
      user-select: none;
      color: white;
      opacity: 0.7;
      justify-content: space-between;
      transition: opacity 0.4s;
    }
    
    .wrapper .roller:hover,
    .wrapper .roller.rolling {
      opacity: 1;
      --last-step-opacity: 0.7;
    }
    
    .wrapper .roller:hover {
      --last-step-opacity: 1;
    }
    
    .wrapper .roller > span {
      height: 20%;
      display: flex;
      justify-content: flex-end;
      align-items: center;
    }
    
    .wrapper.rolling-in {
      pointer-events: none;
    }
    
    .rolling-in .icon {
      opacity: 0;
      pointer-events: none;
      transition: 0.24s ease-out;
    }
    
    .rolling-in .copied {
      transform: translateY(-400%);
      transition: 0.46s 0.1s ease-out;
    }
    
    .rolling-in.rolling-out .icon {
      opacity: 1;
      pointer-events: none;
      transition: 0.24s 0.34s ease-out;
    }
    
    .rolling-in.rolling-out .copied {
      transition: 0.46s 0.1s ease-in;
      transform: translateY(-800%);
    }
    <link href="https://fonts.googleapis.com/css?family=Open+Sans&display=swap" rel="stylesheet">
    <div onclick="toggleRolling(this)" class="wrapper">
      <div class="roller">
        <span class="icon"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" > <path fill-rule="evenodd" clip-rule="evenodd" d="M12 12H14C15.1046 12 16 11.1046 16 10V2C16 0.895431 15.1046 0 14 0H6C4.89543 0 4 0.895431 4 2V4H2C0.895431 4 0 4.89543 0 6V14C0 15.1046 0.895431 16 2 16H10C11.1046 16 12 15.1046 12 14V12ZM14 2H6V4H10C11.1046 4 12 4.89543 12 6V10H14V2ZM10 6H2L2 14H10V6Z" fill="currentColor" /></svg></span>
        <span class="copied">Copied!</span>
      </div>
    </div>

    我还在包装器中添加了pointer-events: none,以便在动画发生时不会导致双击。所以,这些类现在被添加到.wrapper,而不是.roller

    【讨论】:

    • 感谢 mate 会仔细研究这种方法 - 乍一看,对于调试/理解会发生什么以及何时发生的事情看起来相当复杂,无论如何,这很有趣,在动画期间使用 pointer-events 的好技巧
    • 是的,我认为它可以简化更多。基本上,您只需要处理基于类 .rolling-in.rolling-out 的两个动画阶段。
    猜你喜欢
    • 1970-01-01
    • 2013-06-22
    • 2013-01-18
    • 1970-01-01
    • 1970-01-01
    • 2019-02-27
    • 1970-01-01
    • 2012-08-09
    • 1970-01-01
    相关资源
    最近更新 更多