如何通过编程在CSS动画中堆叠关键帧

3
我想在以下代码中使用CSS关键帧(animation-delay)叠加动画效果,但不知道如何通过编程实现?

        .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->0.5+1=1.5s

以及

r3 delay= r2 delay + r2 duration ->1.5+1=2.5s

在JavaScript中是否有任何按类别提供animation-duration的方法?

我尝试使用Element.getAnimations()来实现这一点,但不确定是否有任何按类别提供动画时长的内容。

我不想手动执行此操作,因为我的svg中有许多类别。

非常感谢您的帮助。


calc() 对你的情况有效吗? - Robert Longson
我可以尝试并让您知道是否有计算解决方案。 - smpa01
https://developer.mozilla.org/en-US/docs/Web/CSS/calc() - Robert Longson
如何在当前类中使用calc获取前一个类的动画持续时间? - smpa01
https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties - Robert Longson
2个回答

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 class:

.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
@smpa01 好的,这不是问题,你可以绑定所有你想要的带有动画的类,你需要改变一个查询选择器,对于你的情况,document.querySelectorAll('svg rect') 将起作用,看看吧 :) - Yan Koshelev
1
非常感谢,我会在一两天内尝试并回报。 - smpa01

0

动画链接:使用事件animationend

您可以通过在此事件上使用监听器来链接CSS动画。当元素上的动画已完成(包括动画延迟)时,它将被触发。或者,如果您使用转换,则需要使用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

示例

这里有一个带有链接动画的示例(来自文档):

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>


感谢,但在我的情况下这里不会有任何事件监听器。 - smpa01
你的意思是什么? - gru

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接