Backstory
I was looking through the Vue source code and came across this:
vue.js
function nextFrame(cb) {
requestAnimationFrame(() => {
requestAnimationFrame(cb);
});
}
It turns out that Vue uses the requestAnimationFrame function twice when adding and removing classes during transitions.
What's the purpose of double requestAnimationFrame?
I spent a considerable amount of time trying to understand the reason behind this approach. While I may not have fully grasped its intricacies, here's what I discovered.
Consider this example:
index.html
<button class="btn btn-primary" id="btnStart">Start</button>
<div class="alert alert-success move-animation" id="target">Hello world</div>
style.css
.move-animation {
animation: move 2s linear;
}
@keyframes move {
0% {
transform: translateX(0);
}
50% {
transform: translateX(100px);
}
100% {
transform: translateX(0);
}
}
.testClass {
color: red;
}
script.js
var element = document.getElementById('target');
var btnStart = document.getElementById('btnStart');
function raf(fn) {
window.requestAnimationFrame(function () {
window.requestAnimationFrame(function () {
fn();
});
});
}
function addClass() {
element.classList.add('testClass');
}
btnStart.addEventListener('click', () => {
element.classList.remove('testClass');
raf(addClass);
});
If you decide to test this code, you may not notice a significant difference between raf(addClass);
and simply window.requestAnimationFrame(addClass);
. However, in more complex projects, when a user on a Macintosh device visits your site, they may experience flickering and potentially incorrect rendering of elements during animations. While I cannot provide concrete evidence, rest assured that using the double requestAnimationFrame
method does not introduce more performance overhead than window.requestAnimationFrame(addClass);
. There may be a slight difference, but after extensive browser testing, I did not observe any additional burden.
Summary
Employing double requestAnimationFrame
ensures that the addClass
function executes successfully during the next two consecutive animation steps, resulting in smoother and synchronized animations without undesirable effects.
P.S. Whether or not to utilize this approach is a personal choice. I encourage you to share your thoughts in the comments and engage in discussions regarding this matter. Personally, I find value in using this method, particularly when working with the DOM through JavaScript and dealing with elements that have CSS-defined animations.
Top comments (0)