Reputation: 39
I have question: when I'm drawing a line in canvas, it seems the mouse position doesn't match with the canvas position, so whenever I draw, there is some distance between my cursor and the drawing line .. please help me with this problem, here is my code :
$(document).ready(function(){
context = document.getElementById('canvasInAPerfectWorld').getContext("2d");
$('#canvasInAPerfectWorld').mousedown(function(e){
var mouseX = e.pageX - this.offsetLeft;
var mouseY = e.pageY - this.offsetTop;
paint = true;
addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop);
redraw();
});
$('#canvasInAPerfectWorld').mousemove(function(e){
if(paint){
addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop, true);
redraw();
}
});
$('#canvasInAPerfectWorld').mouseup(function(e){
paint = false;
});
$('#canvasInAPerfectWorld').mouseleave(function(e){
paint = false;
});
});
var clickX = new Array();
var clickY = new Array();
var clickDrag = new Array();
var paint;
function addClick(x, y, dragging)
{
clickX.push(x);
clickY.push(y);
clickDrag.push(dragging);
}
function clear_canvas(){
//alert('masuk claear');
context.clearRect(0,0,context.canvas.width,context.canvas.height);
}
function redraw(){
context.strokeStyle = "#df4b26";
context.lineJoin = "round";
context.lineWidth = 5;
for(var i=0; i < clickX.length; i++) {
context.beginPath();
if(clickDrag[i] && i){
context.moveTo(clickX[i-1], clickY[i-1]);
}else{
context.moveTo(clickX[i]-1, clickY[i]);
}
context.lineTo(clickX[i], clickY[i]);
context.closePath();
context.stroke();
}
}
Upvotes: 3
Views: 3280
Reputation:
You could follow the solution in markE's answer (also found here).
Or you could do the following if your layout allows
layerX
and layerY
to read the mouse positionThis approach gives a little simpler code.
Both methods will be affected by padding and border thickness (they need to be subtracted if any is used). If you want border/padding it's better to wrap the canvas in a div and then style the div instead.
var c = document.querySelector("canvas"),
ctx = c.getContext("2d");
ctx.font = "bold 16px sans-serif";
c.onmousemove = function(e) {
var x = e.layerX,
y = e.layerY;
ctx.clearRect(0, 0, 300, 20);
ctx.fillText("x: " + x + ", y: " + y, 10, 16);
};
div {padding:20px}
canvas {background:#eee; position:relative}
<div><div><canvas></canvas></div></div>
var c = document.querySelector("canvas"),
ctx = c.getContext("2d");
ctx.font = "bold 16px sans-serif";
c.onmousemove = function(e) {
var rect = this.getBoundingClientRect(),
x = e.clientX - rect.left,
y = e.clientY - rect.top;
ctx.clearRect(0, 0, 300, 20);
ctx.fillText("x: " + x + ", y: " + y, 10, 16);
};
div {padding:20px}
canvas {background:#eee; position:relative}
<div><div><canvas></canvas></div></div>
Upvotes: 0
Reputation: 105015
Inside your mouse event handlers, this
refers to the window object and your this.offsetLeft
is undefined.
You can use getBoundingClientRect
to get the bounds of your canvas element:
// get a reference to your canvas element at the start of your app
var canvas=document.getElementById('canvasInAPerfectWorld');
// example mousedown handler
// get the current canvas offsets using getBoundingClientRect
var BB=canvas.getBoundingClientRect();
var offsetX=BB.left;
var offsetY=BB.top;
// calculate the current mouse position relative to the canvas
// using e.client and the offsets calculated above
var mouseX=parseInt(e.clientX-offsetX);
var mouseY=parseInt(e.clientY-offsetY);
If you canvas does not reposition relative to the viewport, you can get the offsets once at the start of your app so they don't need to be recalculated every time inside the mouse handler.
Upvotes: 3