Martijnh
Martijnh

Reputation: 353

Dynamic css content performance

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

Answers (1)

ifthenelse
ifthenelse

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

Related Questions