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

135
Visualizações
HTML Canvas clearRect & Redraw Performance

I am creating a web based drawing board. Part of the functionality of this is to draw shapes (like lines).

I'm finding myself needing to keep track of all the points drawn in the canvas in an array. Specifically because I need to clear the board and redraw the points when drawing lines and other shapes to make it feel "interactive". To clarify the functionality, I've created this JSFiddle https://jsfiddle.net/hwa95rcx/35/

HTML:

<canvas id="test" width="500" height="500">
</canvas>

JavasScript:

let lineStartX = 0;
let lineStartY = 0;
const drawingPoints = [];
let mouseDown = false;
const c = document.getElementById("test");
const ctx = c.getContext("2d");
c.onmousedown = (e) => {
  lineStartX = e.clientX;
  lineStartY = e.clientY;
  mouseDown = true;
}
c.onmousemove = (e) => {
  if (mouseDown) {
    ctx.beginPath();
    ctx.clearRect(0, 0, 500, 500);
    redraw();
    ctx.moveTo(lineStartX, lineStartY);
    ctx.lineTo(e.clientX, e.clientY);
    ctx.stroke();


  }
}
c.onmouseup = (e) => {
  mouseDown = false;
  drawingPoints.push({
    startX: lineStartX,
    startY: lineStartY,
    lineEndX: e.clientX,
    lineEndY: e.clientY
  });
}

function redraw() {
  drawingPoints.forEach(el => {
    ctx.moveTo(el.startX, el.startY);
    ctx.lineTo(el.lineEndX, el.lineEndY);
    ctx.stroke()
  });
}

that exemplifies the reason I need to store an array of points to redraw.

I would like to avoid doing this because at large quantities of data, the drawing slows down or even crashes because we are looping through all the points to redraw them. Is there a more performant way of achieving this interactive shape drawing effect I am looking for?

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

0

Your redraw function calls stroke() for every sub-segment, but never calls beginPath(). This means that when you have two sub-segments, the first one will get painted at its own turn, and then again when the second sub-segment calls stroke().
You can see this quite clearly by looking at your first strokes and how their antialiasing darkens the more sub-segments there are.
You are actually asking the computer to render magnitudes more items than required, this is what is making your app slow and eventually crash.

So you could call beginPath() in the loop, but the best is instead to remove entirely stroke() from there. This way, at every frame you only paint one single path. The GPU has only one single operation to do and you should be fine for days of drawings.

let lineStartX = 0;
let lineStartY = 0;
const drawingPoints = [];
let mouseDown = false;
const c = document.getElementById("test");
const ctx = c.getContext("2d");
c.onmousedown = (e) => {
  lineStartX = e.clientX;
  lineStartY = e.clientY;
  mouseDown = true;
}
c.onmousemove = (e) => {
  if (mouseDown) {
    ctx.beginPath();
    ctx.clearRect(0, 0, 500, 500);
    redraw();
    ctx.moveTo(lineStartX, lineStartY);
    ctx.lineTo(e.clientX, e.clientY);
    ctx.stroke();
  }
}
c.onmouseup = (e) => {
  mouseDown = false;
  drawingPoints.push({
    startX: lineStartX,
    startY: lineStartY,
    lineEndX: e.clientX,
    lineEndY: e.clientY
  });
}

function redraw() {
  // 'redraw' only traces the previous sub-segments
  drawingPoints.forEach(el => {
    ctx.moveTo(el.startX, el.startY);
    ctx.lineTo(el.lineEndX, el.lineEndY);
  });
}
<canvas id="test" width="500" height="500"></canvas>

Note that if you measure that even the tracing takes some computation time (though this would be surprising), you may want to try storing the sub-path in a Path2D object instead of calling the drawing methods every time:

let lineStartX = 0;
let lineStartY = 0;
const path = new Path2D();
let mouseDown = false;
const c = document.getElementById("test");
const ctx = c.getContext("2d");
c.onmousedown = (e) => {
  lineStartX = e.clientX;
  lineStartY = e.clientY;
  mouseDown = true;
}
c.onmousemove = (e) => {
  if (mouseDown) {
    ctx.beginPath();
    ctx.clearRect(0, 0, 500, 500);
    redraw();
    ctx.moveTo(lineStartX, lineStartY);
    ctx.lineTo(e.clientX, e.clientY);
    ctx.stroke();
  }
}
c.onmouseup = (e) => {
  mouseDown = false;
  path.moveTo(lineStartX, lineStartY);
  path.lineTo(e.clientX, e.clientY);
}

function redraw() {
  ctx.stroke(path);
}
<canvas id="test" width="500" height="500"></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