Reputation: 4282
I am trying to stack CSS keyframes (animation-delay) on the following and I am not sure how to do this programmatically?
.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>
The animation-duration
is hardcoded for each class and the animation-delay
is hardcoded for the first class, i.e.r1
.
How can I pass on the delay for r2 and r3, such as
r2 delay= r1 delay + r1 duration->0.5+1=1.5s
and
r3 delay= r2 delay + r2 duration ->1.5+1=2.5s
Is there anything in javascript that gives animation-duration
by class?
I tried doing this by Element.getAnimations() but I am not sure if there is anything that gives animation duration by class.
I don't want to do this manually as I have a lot of class in the svg.
Thank you in advance.
Upvotes: 3
Views: 432
Reputation: 3069
You can chain CSS animations by using a listener on this event. It will be triggered when an animation on an element has been completed (including animation delays). Alternatively, if you use transitions
, you need to use the transitionend event.
Extract the animation properties into a separate class, e.g. .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
Here is an example with chained animations (from the 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>
Upvotes: 0
Reputation: 1129
Set r class for your rects and I think this can help you:
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>
Upvotes: 1