Skip to content

Instantly share code, notes, and snippets.

@jsantell
Last active October 16, 2018 20:49
Show Gist options
  • Save jsantell/23edd6d5ec3e2a1f76c60cfe0057e661 to your computer and use it in GitHub Desktop.
Save jsantell/23edd6d5ec3e2a1f76c60cfe0057e661 to your computer and use it in GitHub Desktop.
Why is there (usually) two rAF callbacks before the next frame? This happens when triggering a transition from a timer (setTimeout) and does not occur when triggering from a rAF
<html><head>
<style>
div {
height: 100px;
width: 100px;
background-color: #35baf6;
transition: width 0.5s;
}
</style>
</head><body>
<div id="test"></div>
<script>
const test = document.querySelector('#test');
let startTransition = 0;
setTimeout(() => {
startTransition = performance.now();
test.style.width = '200px';
requestAnimationFrame(frame);
}, 100);
function frame(t) {
performance.mark('raf-start');
const style = getComputedStyle(test).width;
console.timeStamp(`width: ${style}`);
console.log(`width: ${style}`);
if ((t - startTransition) < 750) {
requestAnimationFrame(frame);
}
performance.mark('raf-end');
performance.measure('rAF', 'raf-start', 'raf-end');
}
</script>
</body>
</html>
@jsantell
Copy link
Author

Two rAF callbacks are called after the element's style has been invalidated before the next frame:

raf-function

@cesutherland
Copy link

image

@cesutherland
Copy link

@jsantell is that what yours looks like ^^^ ?

@cesutherland
Copy link

@jsantell OK I'm on the same page now... comment out line 20 (the rAF) and you still get a delay between when that callback executes and when the actual frame starts, ya?

1000 / 60fps = 16.6ms (the rAF target framerate)

100ms (your setTimeout) is usually right after a frame ended, and a new one started. Change your setTimeout to 99 or 98, I think you'll see the artifact disappear.

@cesutherland
Copy link

I was wrong there, you'll see it twice times :-/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment