nathan-m
nathan-m

Reputation: 8865

Latency when following mouse cursor on <canvas>

I'm trying to draw a rectangle (or other path) at the cursors position.

The issue is, if you move your mouse fast enough, the drawing lags behind the cursor considerably (chases it).

To reproduce/ test the issue, I've tried to produce code that is as lean as possible. However there's still a noticeable gap [between the cursor and the rectangle] due to rendering latency, even on a computer with decent specs (Chrome Beta 37, Fedora 20, i7 4770k, etc)

Can anyone posit to the cause, or suggest improvements to the following code to reduce latency:

http://jsfiddle.net/AGp2w/4/

var canvas = document.getElementsByTagName('canvas')[0];
var canvasDim = {
    width: canvas.width,
    height: canvas.height
};
var canvasOffset = canvas.getBoundingClientRect();

var context = canvas.getContext('2d');
context.stroke = "#000000";
context.fill = "#000000";

var currentPosition = {x:0, y:0};
var previousPosition = currentPosition;
var onlyClearPreviousPositon = true;

canvas.onmousemove = function(e){
    currentPosition = {
        x: e.clientX - canvasOffset.left,
        y: e.clientY - canvasOffset.top
    };
};
function drawAtCursor(){
    if (onlyClearPreviousPositon){
        // experiment - try not clearing the whole canvas 
        context.clearRect(previousPosition.x - 4, previousPosition.y - 4, 8, 8);
        previousPosition = currentPosition;
    } else {
        context.clearRect(0, 0, canvasDim.width, canvasDim.height);
    }
    context.fillRect(currentPosition.x - 4, currentPosition.y - 4, 8, 8);
    window.requestAnimationFrame(drawAtCursor);   
}

drawAtCursor();

Upvotes: 4

Views: 2092

Answers (2)

Adrian
Adrian

Reputation: 1

This is old, but I thought maybe you could draw the cursor (i.e. a fake cursor), turn the real cursor off, finish the move, and then 'rehydrate' the real cursor. Smoke and mirrors

Upvotes: 0

markE
markE

Reputation: 105015

This has a tiny bit less latency, but is not useful in a real app:

function handleMouseMove(e){
    ctx.clearRect(mouseX-1,mouseY-1,9,9);
    mouseX=e.clientX-offsetX;
    mouseY=e.clientY-offsetY;
    ctx.fillRect(mouseX,mouseY,8,8);
}

The mouse pointer will always be quicker than drawing, so your best bet is not to give the user's eye a reason to perceive latency:

Turn off the mouse cursor while the user is drawing.

http://jsfiddle.net/m1erickson/Cf5TX/

The moving rectangle will act as the mouse cursor, but if the user needs a visual guide, you can:

Also draw crosshairs using a couple of lines.

Upvotes: 2

Related Questions