Skip to main content
 首页 » 编程设计

javascript之如何在动画期间更改 animation-timing-function

2026年05月17日68zhengyun_ustc

我有一个动画,我希望元素(文本)在动画中间通过 ease-out 滚入并通过 ease-in 滚出。

所以基本上我想在动画中间更改动画计时功能 - 如何在没有额外 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>

请您参考如下方法:

你可以在没有动画的情况下解决它,但是使用 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