【问题标题】:How to stack keyframes in CSS animation programmatically如何以编程方式在 CSS 动画中堆叠关键帧
【发布时间】:2022-01-29 07:00:52
【问题描述】:

我正在尝试在以下内容上堆叠 CSS 关键帧(动画延迟),但我不确定如何以编程方式执行此操作?

        .r1 {
          animation-name: move1;
          animation-delay: 0.5s;      
          animation-duration: 1s;
          animation-iteration-count: 1;
          animation-timing-function: ease-in;
          animation-direction: normal;
          animation-fill-mode: forwards;
        }
 
        .r2 {
          animation-name: move1;
          animation-delay: 1.5s;      
          animation-duration: 1s;
          animation-iteration-count: 1;
          animation-timing-function: ease-in;
          animation-direction: normal;
          animation-fill-mode: forwards;
        }
             .r3 {
          animation-name: move1;
          animation-delay: 2.5s;      
          animation-duration: 1s;
          animation-iteration-count: 1;
          animation-timing-function: ease-in;
          animation-direction: normal;
          animation-fill-mode: forwards;
        }
 
        @keyframes move1 {
          to {
            transform: translateX(200px);
          }  
        }
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1280 720">
<rect class="r1" x="10" y="20" width="100" height="100" fill="red"/>
    <rect class="r2" x="10" y="130" width="100" height="100" fill="green"/>
    <rect class="r3" x="10" y="240" width="100" height="100" fill="blue"/>
</svg>

animation-duration 是硬编码的每个类,animation-delay 是硬编码的第一类,即r1

如何传递r2和r3的延迟,比如

r2 delay= r1 delay + r1 duration-&gt;0.5+1=1.5s

r3 delay= r2 delay + r2 duration -&gt;1.5+1=2.5s

在 javascript 中有什么东西可以按类给出animation-duration 吗?

我尝试通过 Element.getAnimations() 执行此操作,但我不确定是否有任何东西可以按类提供动画持续时间。

我不想手动执行此操作,因为我在 svg 中有很多类。

提前谢谢你。

【问题讨论】:

标签: javascript css svg css-animations


【解决方案1】:

为你的矩形设置 r 类,我认为这可以帮助你:

const blocks = document.querySelectorAll('svg rect');

for (let i = 1; i<blocks.length; i++) {
    const element = blocks[i];
  const prevElementStyles = getComputedStyle(blocks[i-1]);

  
  element.style.animationDelay = `${parseFloat(prevElementStyles.animationDelay) + parseFloat(prevElementStyles.animationDuration)}s`;
}

r 类:

.r {
  animation-name: move1;
  animation-delay: 0.5s;      
  animation-duration: 1s;
  animation-iteration-count: 1;
  animation-timing-function: ease-in;
  animation-direction: normal;
  animation-fill-mode: forwards;
}

<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1280 720">
<rect class="r" x="10" y="20" width="100" height="100" fill="red"/>
    <rect class="r" x="10" y="130" width="100" height="100" fill="green"/>
    <rect class="r" x="10" y="240" width="100" height="100" fill="blue"/>
</svg>

【讨论】:

  • 这看起来不错。但是,当我尝试使用 js 生成延迟时,只有当我将相同的动画应用于所有 r 类时,上述内容才会起作用。但在我的情况下,我将对不同的类应用不同的动画,例如 - r1 和 m1(translateX),r2 和 x2(rotate),r3 和 q1(scale)。很抱歉给您添麻烦了。我应该在前面提到过。提前谢谢你。
  • @smpa01 好的,这不是问题,您可以将所有类与您想要的动画绑定,您需要更改查询选择器,因为您的情况可以使用 document.querySelectorAll('svg rect') 检查这个:)
  • 非常感谢,将在一两天内试用并重新报告。
【解决方案2】:

动画链接:使用事件animationend

您可以通过在此事件上使用侦听器来链接 CSS 动画。当元素上的动画完成(包括动画延迟)时会触发它。或者,如果您使用transitions,则需要使用transitionend 事件。

基本工作流程

将动画属性提取到一个单独的类中,例如.animation.

#firstEl.animation {
  // your animation properties
}
#secondEl.animation {
  // your animation properties
}
// etc
const firstEl = document.getElementById('#firstEl');
const secondEl = document.getElementById('#secondEl');
const thirdEl = document.getElementById('#thirdEl');

firstEl.classList.add('animation');
firstEl.addEventListener('animationend', () => {
  // start the 2nd animation
  secondEl.classList.add('animation');
});
secondEl.addEventListener('animationend', () => {
  // start the 3rd animation
  thirdEl.classList.add('animation');
});
// etc

示例

这是一个链接动画的例子(来自docs):

const animation = document.querySelector('p.animation');
const animationEventLog = document.querySelector('.animation-example>.event-log');
const applyAnimation = document.querySelector('.animation-example>button.activate');
let iterationCount = 0;

animation.addEventListener('animationstart', () => {
  animationEventLog.textContent = `${animationEventLog.textContent}'animation started' `;
});

animation.addEventListener('animationiteration', () => {
  iterationCount++;
  animationEventLog.textContent = `${animationEventLog.textContent}'animation iterations: ${iterationCount}' `;
});

animation.addEventListener('animationend', () => {
  animationEventLog.textContent = `${animationEventLog.textContent}'animation ended'`;
  animation.classList.remove('active');
  applyAnimation.textContent = "Activate animation";
});

animation.addEventListener('animationcancel', () => {
  animationEventLog.textContent = `${animationEventLog.textContent}'animation canceled'`;
});

applyAnimation.addEventListener('click', () => {
  animation.classList.toggle('active');
  animationEventLog.textContent = '';
  iterationCount = 0;
  let active = animation.classList.contains('active');
  if (active) {
    applyAnimation.textContent = "Cancel animation";
  } else {
    applyAnimation.textContent = "Activate animation";
  }
});
.container {
  height: 3rem;
}

.event-log {
  width: 25rem;
  height: 2rem;
  border: 1px solid black;
  margin: .2rem;
  padding: .2rem;
}

.animation.active {
  animation-duration: 2s;
  animation-name: slidein;
  animation-iteration-count: 2;
}

@keyframes slidein {
  from {
    margin-left: 100%;
    width: 300%;
  }
  to {
    margin-left: 0%;
    width: 100%;
  }
}
<div class="animation-example">
  <div class="container">
    <p class="animation">You chose a cold night to visit our planet.</p>
  </div>
  <button class="activate" type="button">Activate animation</button>
  <div class="event-log"></div>
</div>

【讨论】:

  • 谢谢,但在我的情况下不会有任何事件监听器
  • 那是什么意思?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-12
  • 2021-12-08
  • 1970-01-01
  • 1970-01-01
  • 2011-12-01
相关资源
最近更新 更多