Is there a simple way to get relative mouse coordinates while moving mouse over HTML5 canvas?
I found this:
function getMousePos(canvas, evt){
// get canvas position
var obj = canvas;
var top = 0;
var left = 0;
while (obj && obj.tagName != 'BODY') {
top += obj.offsetTop;
left += obj.offsetLeft;
obj = obj.offsetParent;
}
// return relative mouse position
var mouseX = evt.clientX - left + window.pageXOffset;
var mouseY = evt.clientY - top + window.pageYOffset;
return {
x: mouseX,
y: mouseY
};
}
But it seems too heavy to me. Is there a reason using frameworks (like Kinetic) when working with canvas to simplify such things?
If you're not using your mousemove on your canvas use this:
$(function () {
canvas = document.getElementById('canvas');
canvas.onmousemove = mousePos;
});
function mousePos(e) {
if (e.offsetX) {
mouseX = e.offsetX;
mouseY = e.offsetY;
}
else if (e.layerX) {
mouseX = e.layerX;
mouseY = e.layerY;
}
}
You could position canvas absolutely and then remove while loop.
Ultimately, if canvas would not move, you could cache it's offset and then use cached value.
And to cover all cases: if canvas would have fixed position, you'll need not consider scrolling: pageXOffset, pageYOffset.
Related
I am using HTML5 Canvas with JavaScript. In the HTML layout, the canvas has a dynamic table above it. The table size is not static and changes at run-time depending on the parameter given. The problem I have is that when the table becomes long, it pushes the canvas down and the drawn image no longer shows. I know the drawn image is there because when I apply the following style code:
canvas {
position: absolute;
top: 0px;
left: 0px
}
the canvas moves to the top and the drawn image appears. Also, when the table is short, the canvas works fine.
I have tried using absolute and relative positioning on the table and canvas elements but that is not helping. I have tried getting the height of the table and applying a margin top to the canvas at run time but that didn't work. I have tried offsets, but they are not working either. I don't know what to do in order to keep the drawn image with the canvas element.
//declare variables
var canvas, context, flag = false;
var offsetX, offsetY;
var prevX; //initial position of mouse along x-axis
var currX; //new position of mouse along x-axis, initially set to 0
var prevY; //initial position of mouse along y axis
var currY; //new position of mouse along y axis, initially set to 0
var dot_draw = false;
var font_color = "black";
function startSignaturePad() {
canvas = document.getElementById('signaturepad'); //get the canvas element
if (canvas) {
context = canvas.getContext("2d"); //get the 2d drawing context
canvas.width = 400;
canvas.height = 150;
width = canvas.width;
height = canvas.height;
}
function reOffset() {
var BB = canvas.getBoundingClientRect();
offsetX = BB.left;
offsetY = BB.top;
}
reOffset();
window.onscroll = function(e) {
reOffset();
}
window.onresize = function(e) {
reOffset();
}
//bind the event listeners to the canvas
canvas.addEventListener("mousemove", function onMouseMove(e) {
getPositionXY('move', e)
}, false);
canvas.addEventListener("mousedown", function onMouseDown(e) {
getPositionXY('down', e)
}, false);
canvas.addEventListener("mouseup", function onMouseUp(e) {
getPositionXY('up', e)
}, false);
canvas.addEventListener("mouseout", function onMouseOut(e) {
getPositionXY('out', e)
}, false);
}
function draw() { //function to draw a dot at a specific position - grabs and then draws the position of x and y
context.beginPath();
context.moveTo(prevX, prevY);
context.lineTo(currX, currY);
context.strokeStyle = font_color;
context.lineWidth = font_size;
context.stroke();
context.closePath();
}
function erase() { //erase what is on the canvas
var erase = confirm("Are you sure you want to erase?");
if (erase) {
context.clearRect(0, 0, width, height);
}
}
function getPositionXY(mouse, e) {
if (mouse == 'down') {
prevX = currX; //reset previous position of x and y
prevY = currY;
currX = (e.clientX - canvas.offsetLeft) < (e.clientX - canvas.offsetX) ? e.clientX - canvas.offsetX : e.clientX - canvas.offsetLeft; //set new position of x and y
currY = (e.clientY - canvas.offsetTop) < (e.clientY - canvas.offsetY) ? e.clientY - canvas.offsetY : e.clientY - canvas.offsetTop;
flag = true;
dot_draw = true;
if (dot_draw) { //draw path while mouse is pressed down
context.textBaseline = "hanging";
context.beginPath();
context.fillStyle = font_color;
context.arc(currX, currY, 2, 0, 2 * Math.PI);
context.closePath();
dot_draw = false;
}
}
if (mouse == 'up' || mouse == "out") {
flag = false; //when mouse is released do nothing
}
if (mouse == 'move') {
if (flag) {
prevX = currX;
prevY = currY;
currX = (e.clientX - canvas.offsetLeft) < (e.clientX - canvas.offsetX) ? e.clientX - canvas.offsetX : e.clientX - canvas.offsetLeft;
currY = (e.clientY - canvas.offsetTop) < (e.clientY - canvas.offsetY) ? e.clientY - canvas.offsetY : e.clientY - canvas.offsetTop;
draw();
}
}
}
canvas {
position: absolute;
top: 0px;
left: 0px
}
<div>
<table>
<!-- some code -->
</table>
</div>
<div id="sigCanvas">
<canvas id="signaturepad" style="border:1px solid;"></canvas>
</div>
Since your canvas can move around, you want the latest position, so get it at the last possible instant.
Since your code works when the canvas is at (0,0), just adding
a call to reOffset() and the very beginning of getPositionXY() might do the trick.
If not, here is how I locate a mouse click relative to the canvas:
function locateMouse(evnt)
{
var x = evnt.pageX;
var y = evnt.pageY;
var c = canvas.getBoundingClientRect();
x = Math.floor(x) - c.left;
y = Math.floor(y) - c.top;
/// then use x and y however you want
}
I'm attempting to take in mouse coordinates from a mouse listener but they are coming in undefined. The mouse listener is being added to the Canvas and the listener is triggering the onMouseMove function, however the event being passed doesn't seem to have any defined x or y coordinates for the mouse position.
I've tried the following variables: event.pageX, event.pageY, event.clientX, event.clientY, event.x, event.y
Any ideas on what I'm doing incorrectly to cause the mouse coordinates to come in undefined? Thanks for any help!
<script>
var boxes;
var canvas;
var context;
$(document).ready(function() {
canvas = document.getElementById("requirement_tree");
context = canvas.getContext("2d");
// Add mouse listener
canvas.addEventListener("mousemove", onMouseMove, false);
});
// Get the current position of the mouse within the provided canvas
function getMousePos(event) {
var rect = canvas.getBoundingClientRect();
if (event.pageX != undefined && event.pageY != undefined) {
x = event.pageX;
y = event.pageY;
} else {
x = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
y = event.clientY + document.body.scrollTop + document.documentElement.scrollTop;
}
console.log("X:" + x);
console.log("Y:" + y);
return {
X: x - rect.left,
Y: y - rect.top
};
}
function onMouseMove(event) {
var mousePos = getMousePos(canvas, event);
var message = 'Mouse position: ' + mousePos.X + ',' + mousePos.Y;
context.font = '10pt Arial'
context.fillStyle = 'black';
context.textAlign = 'left';
context.clearRect(0, 0, 200, 200);
context.fillText(message, 100, 100);
}
</script>
At least, error in handler for mouseMove event. Event object transmitted in second arguments of handler.
// ...
// Get the current position of the mouse within the provided canvas
function getMousePos(element, event) {
var rect = canvas.getBoundingClientRect();
// ...
I'm trying to get a good mouse movement in my scene so I can rotate around the object.
I have two problems, I can figure out how to limit the movement so that it never rotates below 0 degrees on the Y axis. (I dont want to see the object from below, only above)
And the second thing I can't figure out is how to make the movement smooth. Now with what I have achieved in the jsfiddle is that the camera moves back to its starting position before starting to rotate.
My try: http://jsfiddle.net/phacer/FHD8W/4/
This is the part I dont get:
var spdy = (HEIGHT_S / 2 - mouseY) / 100;
var spdx = (WIDTH / 2 - mouseX) / 100;
root.rotation.x += -(spdy/10);
root.rotation.y += -(spdx/10);
What I want without using an extra library: http://www.mrdoob.com/projects/voxels/#A/afeYl
You can rotate you scene with this code,
To ensure to not rotate under 0, simule rotation of a vector (0,0,1) and check if y of vector is negative
var mouseDown = false,
mouseX = 0,
mouseY = 0;
function onMouseMove(evt) {
if (!mouseDown) {
return;
}
evt.preventDefault();
var deltaX = evt.clientX - mouseX,
deltaY = evt.clientY - mouseY;
mouseX = evt.clientX;
mouseY = evt.clientY;
rotateScene(deltaX, deltaY);
}
function onMouseDown(evt) {
evt.preventDefault();
mouseDown = true;
mouseX = evt.clientX;
mouseY = evt.clientY;
}
function onMouseUp(evt) {
evt.preventDefault();
mouseDown = false;
}
function addMouseHandler(canvas) {
canvas.addEventListener('mousemove', function (e) {
onMouseMove(e);
}, false);
canvas.addEventListener('mousedown', function (e) {
onMouseDown(e);
}, false);
canvas.addEventListener('mouseup', function (e) {
onMouseUp(e);
}, false);
}
function rotateScene(deltaX, deltaY) {
root.rotation.y += deltaX / 100;
root.rotation.x += deltaY / 100;
}
Is there a simple way to make sure that your shapes stay inside the canvas, when using the drag&drop functionality from KineticJS?
Standard, the shape leaves the canvas a bit until your mouse hits the canvas border. I would like that to be the shapes border, instead of the mouse.
Is there a way to make that happen?
Use dragBoundFunc explained in the KineticJS tutorial
Here's a JS fiddle
And the code:
dragBoundFunc: function(pos) {
console.log(bbox.getWidth());
var xBound = stage.getWidth() - bbox.getWidth();
var yBound = stage.getHeight() - bbox.getHeight();
// Check X boundries
if (pos.x > xBound) {
var newX = xBound;
} else if (pos.x <= 0) {
var newX = 0;
} else {
var newX = pos.x;
}
// Check Y boundries
if (pos.y > yBound) {
var newY = yBound;
} else if (pos.y <= 0) {
var newY = 0;
} else {
var newY = pos.y;
}
return {
x: newX,
y: newY
};
}
I been searching around to find how to get the mouse position relative to canvas but without a JS library...can't see to find any examples except for jquery!
I use this to start my function:
canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
canvas.addEventListener("mousedown", mousePos, false);
But e.pageX and e.pageY is affected by the position of the canvas. I need to remove that issue so the maths is correct so its only based on the canvas.
Can this be done without a JS library? As I have only ever seen it done with jquery which i'm trying to avoid as much as possible.
var findPos = function(obj) {
var curleft = curtop = 0;
if (obj.offsetParent) {
do {
curleft += obj.offsetLeft;
curtop += obj.offsetTop;
} while (obj = obj.offsetParent);
}
return { x : curleft, y : curtop };
};
Get the position of the canvas element and subtract the x and y from it.
I'm using :
var x;
var y;
if (e.pageX || e.pageY)
{
x = e.pageX;
y = e.pageY;
}
else {
x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
}
x -= gCanvasElement.offsetLeft;
y -= gCanvasElement.offsetTop;
First you need to get the offset of the canvas element, or how far right + down it is from the top-left corner.
When the mouse moves, factor in the offset variables to the mouse's position.
This code should do the trick:
var canvas = document.getElementById("canvas");
var xOff=0, yOff=0;
for(var obj = canvas; obj != null; obj = obj.offsetParent) {
xOff += obj.scrollLeft - obj.offsetLeft;
yOff += obj.scrollTop - obj.offsetTop;
}
canvas.addEventListener("mousemove", function(e) {
var x = e.x + xOff;
var y = e.y + yOff;
var ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, 100, 100);
ctx.fillText(x + " - " + y, 40, 40);
}, true);