David John Welsh
David John Welsh

Reputation: 1569

Mouse coordinates drift in HTML5 canvas drawing app

I am creating a simple drawing app using the HTML5 canvas element. The program logic works fine, and everything runs great, except for one thing.

When I draw the first line, the mouse coordinates and the line match perfectly. However, after each subsequent line, the coordinates of the line being drawn are about 0.5~1px off. These discrepancies accumulate, and the effect is readily visible after drawing about ten separate lines. This occurs in all browsers.

For a live example, check this fiddle. I have stripped down everything as much as I could. Obviously the real app is a lot more complex, but even in this simplified version the problem persists, which leads me to think I'm missing something incredibly obvious.

It occurred to me that I might be somehow rounding up the coordinates, which is about the only thing I can think of that could account for such a gradual drift. I was using a proprietary function for getting the offset values, so I tried using jQuery (since that has never given me problems in the past) but nothing changed.

Please help me figure out why this is happening!


Apparently I need to post code now in order to link to jsfiddle. I have no idea which part of the code might be wrong, so I apologise in advance for posting everything and creating a wall of text.

var offsetX = 0, offsetY = 0;
var currentMouseCoords = {
    x : 0,
    y : 0
};
var drawPing = null;
var ctx = null;

$('#cover').mousedown(function (event) {
    event.preventDefault();

    var f = $(this).offset();
    offsetX = f.left;
    offsetY = f.top;

    currentMouseCoords.x = event.pageX - offsetX;
    currentMouseCoords.y = event.pageY - offsetY;

    drawStart();

    if (!drawPing) {
        drawPing = setInterval(draw, 10);
    }
})
.mousemove(function (event) {

    currentMouseCoords.x = event.pageX - offsetX;
    currentMouseCoords.y = event.pageY - offsetY;

})
.mouseout(function (event) {
    //When mouse leaves canvas, quit drawing
    drawEnd();
})
.mouseup(function (event) {
    //When mouse leaves canvas, quit drawing
    drawEnd();
})


/* Functions that perform the actual drawing */

function drawStart () {
    //Get canvas context
    ctx = document.getElementById('canvas').getContext("2d");
    ctx.translate(0.5,0.5);

    //Set styles
    ctx.strokeStyle = '#333333';
    ctx.lineCap = 'round';
    ctx.lineJoin = 'round';
    ctx.lineWidth = 1;

    //Begin path
    ctx.beginPath();
    ctx.moveTo(
        currentMouseCoords.x,
        currentMouseCoords.y
    );

}

function draw () {
    ctx.lineTo(
        currentMouseCoords.x, 
        currentMouseCoords.y
    );
    ctx.stroke();
}

function drawEnd () {
    clearInterval(drawPing);
    drawPing = null;
    if (ctx) {
        ctx.closePath();
        ctx = null;
    }
}

I imagine it'll make a lot more sense if you just look at the actual fiddle....


For the record, I googled for quite a while to see if anyone else had this issue, but either it's not that common or I can't find the right combination of words. There are myriad problems with mouse coordinates but none of them seem to be the same as the one I am experiencing.

Upvotes: 0

Views: 676

Answers (1)

markE
markE

Reputation: 105015

You are repeatedly translating in your drawStart function and those translations are accumulating:

ctx.translate(0.5,0.5)

You can reverse the translate with translate(-.5,-.5) or wrap your drawing code in ctx.save()/ctx.restore().

You might also want to move your ctx=document... outside the drawStart "loop" for better performance.

//Get canvas context outside drawStart

ctx = document.getElementById('canvas').getContext("2d");

Upvotes: 1

Related Questions