Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

169
Visualizações
Use GPU to draw on HTML5 Canvas on Google Chrome

I'm using a canvas to draw a marker (in SVG) hundreds (sometimes thousands) of times. The size of the canvas is 300x300 pixels and the SVG is 18x25 pixels.

The code is quite straigth forward, I have a for loop where I draw the markers on the canvas:

   drawNewTile = (canvas, points) => {
        const drawn = {};
        const context = canvas.getContext('2d');
        if (points.length === 0) return;
        for (let i = points.length; i -= 1;) {
            const [x, y] = points[i];
            if (!drawn[`${x}:${y}`]) {
                drawn[`${x}:${y}`] = true;
                this.drawMarker(context, x, y);
            }
        }
    };

    drawMarker = (context, x, y) => {
        const x_ = Math.floor(x - this.MARKER_WIDTH / 2 + this.MAX_DIMENSION_OF_MARKER);
        const y_ = Math.floor(y - this.MARKER_HEIGHT + this.MAX_DIMENSION_OF_MARKER);
        context.drawImage(this.marker, x_, y_, this.MARKER_WIDTH, this.MARKER_HEIGHT);
    }; 

I have already put in place some optimizations: like the for loop, only draw those points which are not already drawn, use integer coordinates, etc.

After that, I have some good results, but my page it gets a little bit stuck on Google Chrome. Nonetheless, to my surprise, in Firefox it goes fast as hell, like, really really fast. So I made some digging with the performance tab of Google Chrome and I found that my code was using a lot of CPU and that's slow.

I also found this article where it says that Chrome uses some heuristics to determine if it uses a CPU or a GPU to draw the canvas.

So, my question is, how do I force the use of GPU on Chrome? Is there any flag I can set or something similar? Do you any other way to speed that the drawing process?

about 4 years ago · Juan Pablo Isaza
1 Respostas
Responde à pergunta

0

The problem is that apparently Chrome keeps SVG images in the CPU, and rasterizes it at every new call to drawImage().

Simply rasterizing it yourself will make Chrome's performances grow instantly.

To do that, use the createImageBitmap() method, which will create an ImageBitmap that the browser will be able to store directly in the GPU's memory.
Safari just did expose this method in the newest version of their browser, so you may still want to use a polyfill for it. While in this case, simply drawing on a canvas would be enough, I made such a polyfill which does include a few features that most browsers don't support yet.

(async () => {
  const canvas = document.querySelector("canvas");
  const ctx = canvas.getContext("2d");
  const select = document.querySelector("select");
  const html_img = new Image();
  const svg_str = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 18 25" width="18" height="25">
    <circle cx="9" cy="9" r="6"/>
  </svg>`;
  const svg_blob = new Blob([svg_str], {
    type: "image/svg+xml"
  });

  ctx.font = "20px sans-serif";
  ctx.fillStyle = "red";

  html_img.src = URL.createObjectURL(svg_blob);
  const sources = {
    html_img,
    bitmap: await createImageBitmap(svg_blob)
  };
  const times = [];
  await html_img.decode();

  anim();

  function anim() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    for (let y = 0; y < canvas.width; y += 10) {
      for (let x = 0; x < canvas.width; x += 5) {
        ctx.drawImage(sources[select.value], x, y);
      }
    }
    requestAnimationFrame(anim);

    // ultra rough FPS counter
    const now = performance.now();
    while (times.length > 0 && times[0] <= now - 1000) {
      times.shift();
    }
    times.push(now);
    fps = times.length;
    ctx.fillText(fps + "FPS", 30, 30);
  }
})();
<!-- createImageBitmap polyfill for old browsers --> <script src="https://cdn.jsdelivr.net/gh/Kaiido/createImageBitmap/dist/createImageBitmap.js"></script>
source: <select>
  <option value="bitmap">ImageBitmap</option>
  <option value="html_img">HTMLImage</option>
</select><br>
<canvas width="300" height="300"></canvas>

about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda