Reputation: 353
I have a requestAnimationFrame loop where i need to set the innerText to the fps measured using javascript. I was wondering if there's a more efficient way to do this (as i think setting the innerText will cause a reflow/repaint every frame)? For just the fps this will probably not cause any performance hit, but as i want to add/change many more elements using this mechanism i was wondering if there's a more efficient way to do this?
I tried changing a css variable: #fps-counter:before { content: var(--css-fps-var) }
and change --css-fps-var in the loop, but that didnt work.
For now i settled with a data-attribute which i update using an data-attr: #fps-counter:before { content: attr(data-fps); }
I have no clue if that would be more performant, i think it should but im just not sure.. is there's a better way of doing this?
edit1:
Unfortunatly i can't use canvas, i have to use DOM elements to achieve this..
Upvotes: 0
Views: 389
Reputation: 717
Drawing the value as text in a <canvas>
will not trigger any layout / reflow of the DOM:
const times = [];
let fps;
const canvas = document.getElementById('fpsCounter');
const ctx = canvas.getContext('2d');
ctx.font = '16px sans-serif';
function refreshLoop() {
window.requestAnimationFrame(() => {
const now = performance.now();
while (times.length > 0 && times[0] <= now - 1000) {
times.shift();
}
times.push(now);
fps = times.length;
ctx.fillStyle = '#000000';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = '#FFFFFF';
ctx.fillText(`fps: ${fps}`, 10, 16);
refreshLoop();
});
}
refreshLoop();
<canvas id="fpsCounter" width="100" height="20" style="position: absolute; top: 10px; left: 10px;"/>
Upvotes: 1