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

160
Views
Large delay between Canvas `pointerdown` and `pointermove` events with stylus

I'm trying to create a very basic sketch pad using an HTML Canvas and pointer events. I've implemented a very basic codepen that demonstrates the issue at hand. The key functionality draws a red dot upon pointerdown events and a blue dot on pointermove events:

c.addEventListener('pointerdown', event => {
  event.preventDefault();
  updatePosition(event);
  ctx.fillStyle = 'red';
  ctx.fillRect(position.x - 2, position.y - 2, 4, 4);
  drawing = true;
});

c.addEventListener('pointermove', event => {
  if (!drawing) return;
  event.preventDefault();
  updatePosition(event);
  ctx.fillStyle = 'blue';
  ctx.fillRect(position.x - 2, position.y - 2, 4, 4);
});

Both when using a stylus (a Surface Pen) or just touch, I observe a large gap between the initial pointerdown event and the eventual (good) "stream" of pointermove events, as demonstrated here:

enter image description here

I've observed to varying degrees with multiple input methods on different hardware. Is there a way I can eliminate or mitigate this?

about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

Using the fillRect() method isn't the best choice for 'live' interactive drawing. The reason is, that the pointermove event or any event for that matter has finite precision. That is, if you move your mouse fast enough it won't recognize all positions the pointer might have hit during the movement - it might just be the start and end position.

The usual approach for such a scenario is using the lineTo() method instead as it draws a line from the previous to the current position obtained by e.g. a pointermove event. The thickness of such a line can be controlled using the lineWidth property.

Here's your modified example:

const c = document.getElementById('board');

const compStyle = window.getComputedStyle(c);
const width = parseInt(compStyle.getPropertyValue('width').replace('px', ''));
const height = parseInt(compStyle.getPropertyValue('height').replace('px', ''));

c.width = width;
c.height = height;
const ctx = c.getContext('2d');
ctx.lineWidth = 4;
ctx.lineCap = 'round';

const position = {
  x: 0,
  y: 0
};
const updatePosition = (event) => {
  let rect = event.target.getBoundingClientRect();
  position.x = (event.clientX - rect.left) * (width / rect.width);
  position.y = (event.clientY - rect.top) * (height / rect.height);
}

let drawing = false;

c.addEventListener('pointerdown', event => {
  event.preventDefault();

  updatePosition(event);
  ctx.beginPath();
  ctx.strokeStyle = 'red';
  ctx.moveTo(position.x, position.y)
  ctx.arc(position.x, position.y, ctx.lineWidth / 4, 0, 2 * Math.PI);
  ctx.stroke();
  ctx.strokeStyle = 'blue';
  drawing = true;
});

c.addEventListener('pointermove', event => {
  if (!drawing) return;
  event.preventDefault();
  updatePosition(event);
  ctx.lineTo(position.x, position.y);
  ctx.stroke();
});

c.addEventListener('pointerup', event => {
  ctx.closePath();
  drawing = false;
});
#board {
  position: absolute;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  touch-action: none;
}
<canvas id="board"></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!