Sharan De Silva Sharan De Silva - 2 months ago 14
HTML Question

Mouse pointer coordinates and canvas coordinates not matching

I am trying to draw a line using canvas. While drawing a line my mouse pointer coordinates and canvas coordinates are mismatching. If I drag mouse at top of my canvas it draws a line at bottom. Can anyone identify what I am doing wrong here. I tried the below example.

Fiddle : https://jsfiddle.net/Shathiran/bpunb9dn/5/



var canvas, ctx, flag = false, prevX = 0, currX = 0, prevY = 0, currY = 0, dot_flag = false;

var x = "black", y = 2;

function init() {
canvas = document.getElementById('drawCanvas');
ctx = canvas.getContext("2d");
w = ctx.clientWidth;
h = ctx.clientHeight;

canvas.addEventListener("mousemove", function (e) {
findxy('move', e)
}, false);
canvas.addEventListener("mousedown", function (e) {
findxy('down', e)
}, false);
canvas.addEventListener("mouseup", function (e) {
findxy('up', e)
}, false);
canvas.addEventListener("mouseout", function (e) {
findxy('out', e)
}, false);
}

function draw() {
ctx.beginPath();
ctx.moveTo(prevX, prevY);
ctx.lineTo(currX, currY);
ctx.strokeStyle = x;
ctx.lineWidth = y;
ctx.stroke();
ctx.closePath();
}

function findxy(res, e) {
if (res == 'down') {
prevX = currX;
prevY = currY;
currX = e.clientX - canvas.offsetLeft;
currY = e.clientY - canvas.offsetTop;

flag = true;
dot_flag = true;
if (dot_flag) {
ctx.beginPath();
ctx.fillStyle = x;
ctx.fillRect(currX, currY, 2, 2);
ctx.closePath();
dot_flag = false;
}
}
if (res == 'up' || res == "out") {
flag = false;
}
if (res == 'move') {
if (flag) {
prevX = currX;
prevY = currY;
currX = e.clientX - canvas.offsetLeft;
currY = e.clientY - canvas.offsetTop;
draw();
}
}
}
init();

<div class="paper">
<canvas id="drawCanvas" style="width:100%; height:100%;border: 1px solid #000"> </canvas>
</div>




Answer

You are getting the mouse positions fine. The problem here is how you are assigning the width and height of your canvas, mainly because you are setting it via CSS as a style (which "stretches" the canvas) other that the width and height attributes (see this question for more information). To fix this set your width/height as HTML attributes to your canvas.

For example:

var canvas, ctx, flag = false, prevX = 0, currX = 0, prevY = 0, currY = 0, dot_flag = false;
	
	    var x = "black", y = 2;
	    
	    function init() {
	        canvas = document.getElementById('drawCanvas');
            canvas.setAttribute('width', canvas.parentNode.offsetWidth);
            canvas.setAttribute('height', canvas.parentNode.offsetHeight);
	        ctx = canvas.getContext("2d");
	        w = ctx.clientWidth;
	        h = ctx.clientHeight;
          
	        canvas.addEventListener("mousemove", function (e) {
	            findxy('move', e)
	        }, false);
	        canvas.addEventListener("mousedown", function (e) {
	            findxy('down', e)
	        }, false);
	        canvas.addEventListener("mouseup", function (e) {
	            findxy('up', e)
	        }, false);
	        canvas.addEventListener("mouseout", function (e) {
	            findxy('out', e)
	        }, false);
	    }

	    function draw() {
	        ctx.beginPath();
	        ctx.moveTo(prevX, prevY);
	        ctx.lineTo(currX, currY);
	        ctx.strokeStyle = x;
	        ctx.lineWidth = y;
	        ctx.stroke();
	        ctx.closePath();
	    }
	    
	    function findxy(res, e) {
	        if (res == 'down') {
	            prevX = currX;
	            prevY = currY;
                var cRect = canvas.getBoundingClientRect();
	            currX = e.clientX - cRect.offsetLeft;
	            currY = e.clientY - cRect.offsetTop;
	    
	            flag = true;
	            dot_flag = true;
	            if (dot_flag) {
	                ctx.beginPath();
	                ctx.fillStyle = x;
	                ctx.fillRect(currX, currY, 2, 2);
	                ctx.closePath();
	                dot_flag = false;
	            }
	        }
	        if (res == 'up' || res == "out") {
	            flag = false;
	        }
	        if (res == 'move') {
	            if (flag) {
	                prevX = currX;
	                prevY = currY;
	                currX = e.clientX - canvas.offsetLeft;
	                currY = e.clientY - canvas.offsetTop;
	                draw();
	            }
	        }
	    }
	    init();
<div class="paper" width="400">
    <canvas id="drawCanvas" width="200" height="200" style="border: 1px solid #000">     </canvas>
</div>


Note you can set the canvas height and width to 100% by using window.innerWidth and window.innerHeight. Although if you want it to dyncamically change you need to update it on resize:

canvas.setAttribute('width', window.innerWidth);
canvas.setAttribute('height', window.innerHeight);
Comments