Reputation: 443
I'm practicing JavaScript by developing a drawing tool, but I have a few questions about it. First of all, here's what I've got right now: https://jsfiddle.net/w6kLbg2q/
(function($) {
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
//Detect a mouse down. Set the xy coordinates
var mouseDown = false;
$(canvas).mousedown(function(e) {
mouseDown = true;
context.beginPath();
context.moveTo(e.pageX, e.pageY);
});
//Detect that the mouse is moving and draw the line while the mouse is still down
$(canvas).mousemove(function(e) {
if (mouseDown) {
var x = e.offsetX * 2;
var y = e.offsetY * 2;
context.lineTo(x, y);
context.strokeStyle = '#000';
context.stroke();
}
});
//On mouse up, reset the coordinates
$(canvas).mouseup(function() {
mouseDown = false;
context.closePath();
});
})(jQuery);
#canvas {
width: 400px;
height: 400px;
border: 1px solid;
margin: 0 auto;
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="canvas">
This text is displayed if your browser does not support HTML5 Canvas.
</canvas>
e.offsetX * 2;
because I saw this somewhere and it wasn't working when I did e.pageX. Why is that? And why is the * 2 necessary?Thanks in advance!
Upvotes: 2
Views: 123
Reputation: 847
I fixed it! Replace your offsets:
var x = e.offsetX / 1.325;
var y = e.offsetY / 2.65;
Why does this work?
The function in which you use to locate the mouse has a constant offset in both directions. I figured this out when I noticed that the drawing was exponentially farther away then my mouse, but was right on at (0,0) on the graph (because any offset * 0, the coordinate, equals 0). I found the constant offset of the canvas and plugged it in, and it worked! :)
I understand there are other answers, and they are probably more accurate, but it doesn't mean you have to hate on this one :(
Upvotes: -1
Reputation: 54089
The problem has to do with the fact that the canvas resolutions and canvas display size do not match.
Canvas resolution is set via the canvas width and height properties. They can be set as follows
<canvas id="canvasId" width="400" height="400"></canvas>
or via script
canvasId.width = 400;
canvasId.height = 400;
If you do not set these values the canvas will default to 300 by 150.
Display size is the actual size of the canvas as displayed on the page and is set via the style properties width and height
<canvas id="canvasId" style="width:400px;height:400px;"></canvas>
or via script
canvasId.style.width = "400px";
canvasId.style.height = "400px";
or in CSS
#canvasId {
width : 400px;
height : 400px;
}
There are two solutions to your problem.
First is to have the display size match the canvas resolution.
Or you can use the difference between display size and canvas resolution to calculate the scale for the mouse.
var bounds = canvasId.getBoundingClientRect()
mouseScaleX = canvasId.width / bounds.width;
mouseScaleY = canvasId.height / bounds.height;
// then multiply the mouse coords with scales
I have modified your snippet to scale the mouse coords to match the canvas resolution.
(function($) {
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
//Detect a mouse down. Set the xy coordinates
var mouseDown = false;
$(canvas).mousedown(function(e) {
mouseDown = true;
var bounds = e.target.getBoundingClientRect()
mouseScaleX = e.target.width / bounds.width;
mouseScaleY = e.target.height / bounds.height;
context.beginPath();
context.moveTo(e.offsetX * mouseScaleX, e.offsetY * mouseScaleY);
});
//Detect that the mouse is moving and draw the line while the mouse is still down
$(canvas).mousemove(function(e) {
if (mouseDown) {
var bounds = e.target.getBoundingClientRect()
mouseScaleX = e.target.width / bounds.width;
mouseScaleY = e.target.height / bounds.height;
var x = e.offsetX * mouseScaleX;
var y = e.offsetY * mouseScaleY;
context.lineTo(x, y);
context.strokeStyle = '#000';
context.stroke();
}
});
//On mouse up, reset the coordinates
$(canvas).mouseup(function() {
mouseDown = false;
context.closePath();
});
})(jQuery);
#canvas {
width: 400px;
height: 400px;
border: 1px solid;
margin: 0 auto;
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="canvas">
This text is displayed if your browser does not support HTML5 Canvas.
</canvas>
Upvotes: 2
Reputation: 32511
There's a few problems:
Here's how you correctly fix it without magic numbers.
(function($) {
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var mouseDown = false;
$(canvas).mousedown(function(e) {
mouseDown = true;
context.beginPath();
// I'd also suggest changing from pageX/Y to offsetX/Y
// otherwise you get this weird jumping effect
context.moveTo(e.offsetX, e.offsetY);
});
$(canvas).mousemove(function(e) {
if (mouseDown) {
// Remove the multiplier
var x = e.offsetX;
var y = e.offsetY;
context.lineTo(x, y);
context.strokeStyle = '#000';
context.stroke();
}
});
$(canvas).mouseup(function() {
mouseDown = false;
context.closePath();
});
})(jQuery);
#canvas {
/* You don't need to set the size here */
border: 1px solid;
margin: 0 auto;
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- Notice how I set the size of the canvas -->
<canvas id="canvas" width="400" height="400">
This text is displayed if your browser does not support HTML5 Canvas.
</canvas>
Upvotes: 1