Skip to content

Instantly share code, notes, and snippets.

@ryanmorr
Last active April 2, 2024 06:45
Show Gist options
  • Save ryanmorr/068709f325c3d6ca8610230c2bb622dc to your computer and use it in GitHub Desktop.
Save ryanmorr/068709f325c3d6ca8610230c2bb622dc to your computer and use it in GitHub Desktop.
Simple abstraction for using requestAnimationFrame
let raf = 0;
const animations = [];
function remove(animation) {
const index = animations.indexOf(animation);
if (index > -1) {
animations.splice(index, 1);
}
}
function tick(timestamp) {
for (let i = animations.length; i--;) animations[i](timestamp);
raf = (animations.length > 0) ? requestAnimationFrame(tick) : 0;
}
function animate(update) {
if (raf === 0) {
raf = requestAnimationFrame(tick);
}
return new Promise((resolve) => {
const done = () => (resolve(), remove(animation));
const animation = (timestamp) => update(timestamp, done);
animations.push(animation);
});
}
// Usage:
let startTime;
const duration = 1000;
const element = document.querySelector('.foo');
await animate((timestamp, done) => {
// Calculate tween
if (!startTime) {
startTime = timestamp;
}
const elapsed = Math.min(timestamp - startTime, duration);
// Update the element
element.style.translateX = (0.1 * elapsed) + 'px';
// When the animation is complete, call the `done()` function
if (elapsed / duration >= 1) {
done();
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment