I want to make a css animation editor tool using css keyframes animations.
The idea is to have a timeline to play and preview a css animation, and settle keyframes on.
The problematic is for the animation preview, i have to interpolate the style of my html element at a specific timepoint between two keyframes. It can be calculated in js for simple value ( such as top position number for example ), but in some scenario it can be tricky to interpolate some css properties in js ( for example border-radius, how to interpolate a value from "50% 20% 10% 10%" to "20% / 10%" ??? )
One idea to solve that is to play and interpret css keyframe animation only at a specific keyframe.
But it seems to be complicated to play only specific range of a css animation. I know there are the animation-range, animation-range-start and animation-range-end css properties, but these properties are still experimental and does not seems to work in my scenario.
So currently i have no idea how to solve that in the best way. The js interpolation way is doable but complex for specific scenario as explained (how to blend a css border radius style value between border-radius: 10% 30% 50% 70%; and border-radius: 10% / 50%; ?), and the css way is complex to solve in a proper way.
This is what i tried with css
<head>
<style>
@keyframes colorAnim {
0% {
color: black;
}
50% {
color: red;
}
100% {
color: green;
}
}
.animated-element-with-offset {
animation: colorAnim 100ms infinite;
animation-play-state: paused;
}
</style>
</head>
<body>
<div class="animated-element-with-offset" id="some-element-you-want-to-animate">
Text Color Animation frame #50: Color expected is red
</div>
<button onclick="interpretAndPauseAnimation(50)">Interpret and Pause Animation at 50%</button>
<script>
const element = document.getElementById("some-element-you-want-to-animate");
let start, previousTimeStamp;
let duration = 100;
let endDuration = 49;
let done = false;
function step(timeStamp) {
if (start === undefined) {
start = timeStamp;
}
const elapsed = timeStamp - start;
if (previousTimeStamp !== timeStamp) {
if (elapsed > duration * (endDuration / 100)) {
done = true;
element.style.animationPlayState = 'paused';
} else {
element.style.animationPlayState = 'running';
}
}
if (elapsed < duration) {
// Stop the animation after 2 seconds
previousTimeStamp = timeStamp;
if (!done) {
window.requestAnimationFrame(step);
}
}
}
function interpretAndPauseAnimation(keyframePercentage) {
start = undefined;
previousTimeStamp = undefined;
done = false;
window.requestAnimationFrame(step);
}
window.requestAnimationFrame(step);
</script>
</body>
</html>
2
Answers
Rely on negative delays to get a specific point
The best at controlling CSS animations through JS is certainly the Web Animations API.
You can access a CSSAnimation object representing the CSS
animation
you’ve set on your element and then control itscurrentTime
(and many more if needed). You can access its duration through thegetTiming()
method of itsKeyframeEffect
.effect
.