Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

136
Views
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 answers
Answer question

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!