coordinates mouse canvas - javascript

So ... I created canvas element with jquery:
var canvasElement = $("<canvas id='map' width='" + CANVAS_WIDTH + "' height='" + CANVAS_HEIGHT + "'></canvas");
var canvas = canvasElement.get(0).getContext("2d");
canvasElement.appendTo('body');
And now i want to get mouse coordinates, but the next code doesn't work:
canvasElement.onmousemove = mousemove;
function mousemove(evt) {
var mouseX = evt.pageX - canvasElement.offsetLeft;
var mouseY = evt.pageY - canvasElement.offsetTop;
alert(mouseX+":"+mouseY);
}
canvasElement.offsetLeft is not work, evt.pageX too... Help !

Those properties aren't cross-browser.
I know of two solutions to get the canvas position :
the easy one : use jQuery offset
another one : use a custom and complex code :
if (!canvasElement.offsetX) {
// firefox
var obj = canvasElement;
var oX = obj.offsetLeft;var oY = obj.offsetTop;
while(obj.parentNode){
oX=oX+obj.parentNode.offsetLeft;
oY=oY+obj.parentNode.offsetTop;
if(obj==document.getElementsByTagName('body')[0]){break}
else{obj=obj.parentNode;}
}
canvas_position_x = oX;
canvas_position_y = oY;
} else {
// chrome
canvas_position_x = canvasElement.offsetX;
canvas_position_y = canvasElement.offsetY;
}
As there is a loop, you'd better store canvas_position_x and canvas_position_y and have them recomputed at each document resize instead of at each mousemove.
Demonstration

Live Demo
Its pretty easy actually without jQuery. Below is the important part from the fiddle. cX and cY are the coordinates of the clicked canvas.
function clicked(e) {
var cX = 0,
cY = 0;
if (event.pageX || event.pageY) {
cX = event.pageX;
cY = event.pageY;
}
else {
cX = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
cY = event.clientY + document.body.scrollTop + document.documentElement.scrollTop;
}
cX -= canvas.offsetLeft;
cY -= canvas.offsetTop;
ctx.fillRect(cX, cY, 2, 2);
}​
Demo with mouse move

Related

Javascript/Canvas: Mouse coordinates don't match after scaling (collision)

After resizing the square, there is a collision problem, GIF animation problem, sample https://jsfiddle.net/8jkxdhfv/. What can i do? Should i untransformed mouse coordinates to transformed coordinates ? But how? How can i update x and y in my collision function?
HTML
<canvas id="test" width="480" height="380"></canvas>
<div id="text">Use mouse wheel to change square size</div>
JAVASCRIPT
var ctx = test.getContext('2d');
var obj = { x:100,y: 100,width: 100,height: 100}
var mouse = {x:0, y:0, width:10, height:10};
var zoom = 1;
setInterval(function(){
ctx.clearRect(0,0,test.width,test.height);
ctx.save();
var cx = obj.x+obj.width/2;
var cy = obj.y+obj.height/2;
// draw
ctx.translate(cx, cy);
ctx.scale(zoom,zoom);
ctx.translate(-cx,-cy);
ctx.fillRect(obj.x,obj.y,obj.width,obj.height);
ctx.restore();
// check collision
if(collision(obj,mouse)){
ctx.fillText("===== COLLISION =====", 110,90);
}
},1000/60);
function collision(obj1,obj2){
if(obj1.x < obj2.x + obj2.width * zoom &&
(obj1.x + obj1.width * zoom) > obj2.x &&
obj1.y < obj2.y + obj2.height * zoom &&
(obj1.height * zoom + obj1.y) > obj2.y){
return true;
}
return false;
}
window.addEventListener('mousewheel', function(e){
if(e.deltaY>0 && zoom<2){
zoom+=0.5;
}
if(e.deltaY<0 && zoom>0.5){
zoom-=0.5;
}
}, false);
window.addEventListener('mousemove', function(e){
mouse.x = e.pageX;
mouse.y = e.pageY;
}, false);
You are getting mouse position based on entire window, not canvas. Some math and you will get what you want.
test.addEventListener("mousemove", function(evt) {
var mousePos = getMousePos(test, evt);
mouse.x = mousePos.x;
mouse.y = mousePos.y;
});
function getMousePos(canvas, event) {
var rect = canvas.getBoundingClientRect();
return {
x: event.clientX - rect.left,
y: event.clientY - rect.top
};
}
I have updated the function and it works:
function collision(obj1,obj2){
var eW = (obj1.width-(obj1.width*zoom))/2;
var eH = (obj1.height-(obj1.height*zoom))/2;
//console.log(eW);
if(obj1.x+eW < obj2.x + obj2.width * zoom &&
(obj1.x + obj1.width * zoom) + eW> obj2.x &&
obj1.y + eH < obj2.y + obj2.height * zoom &&
(obj1.height * zoom + obj1.y) + eH > obj2.y){
return true;
}
return false;
}

HTML5 Canvas Mouse Listener Coordinates Undefined

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();
// ...

angularjs: rescaling textbox

I'm trying to make an editable textbox like those in powerpoint and other presentation editors.
This is my feeble attempt.
I'm having trouble with the initial rescaling. To be concise, the first instant when I adjust the drag handle, the box does not scale to the correct height and width.
Any idea why is that so?
element.find('span').bind('mousedown', function(event) {
console.log('resizing...');
event.preventDefault();
var domElement = element[0];
var rect = domElement.getBoundingClientRect();
startX = rect.left;
startY = rect.bottom;
console.log(startX + " " + startY);
$document.bind('mousemove', resize);
$document.bind('mouseup', mouseup2);
event.cancelBubble = true;
});
function resize(event) {
var height = event.screenY - startY;
var width = event.screenX - startX;
scope.$apply(function() {
scope.tb.height = height + 'px';
scope.tb.width = width + 'px';
});
}
I updated your fiddle implementing this:
tbW and tbH hold the current box size (inital 200px x 100px):
var tbW = 200,
tbH = 100;
scope.tb.width = tbW + 'px',
scope.tb.height = tbH + 'px';
On mousedown startX and startY are assigned to the current mouse postion
In the resize function the delta of the mouse movement is calculated and added to the width and height of your tbox:
tbH += event.screenY - startY;
startY = event.screenY;
tbW += event.screenX - startX;
startX = event.screenX;
scope.$apply(function () {
scope.tb.height = tbH + 'px';
scope.tb.width = tbW + 'px';
});

Mouse position in canvas without a library?

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);

How can I detect the distance that the user's mouse has moved?

I'm trying to detect the distance the mouse has moved, in pixels. I am currently using:
$(document).mousemove(function(event) {
var startingTop = 10,
startingLeft = 22,
math = Math.abs(((startingTop - event.clientY) + (startingLeft - event.clientX)) + 14) + 'px';
$('span').text('From your starting point(22x10) you moved: ' + math);
});
However, I don't feel like this is the right way to do this, or is it? It doesn't feel to consistent to me.
Here is a demo of how it is working right now: http://jsfiddle.net/Em4Xu/1/
Extra Details:
I'm actually developing a drag & drop plugin and I want to create a feature called distance, like draggable has it, where you have to pull your mouse a certain amount of pixels before it drags. I'm not 100% sure how to do this, so first I need to get the pixels that the mouse has moved from the startingTop and startingLeft position.
Does anyone have any suggestions?
Here's a version that meters distance that mouse travels:
var totalDistance = 0;
var lastSeenAt = {x: null, y: null};
$(document).mousemove(function(event) {
if(lastSeenAt.x) {
totalDistance += Math.sqrt(Math.pow(lastSeenAt.y - event.clientY, 2) + Math.pow(lastSeenAt.x - event.clientX, 2));
$('span').text('So far your mouse ran this many pixels: ' + Math.round(totalDistance));
}
lastSeenAt.x = event.clientX;
lastSeenAt.y = event.clientY;
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span></span>
You got your math wrong. Here's improved version: http://jsfiddle.net/stulentsev/Em4Xu/26/
$(document).mousemove(function(event) {
var startingTop = 10,
startingLeft = 22,
math = Math.round(Math.sqrt(Math.pow(startingTop - event.clientY, 2) +
Math.pow(startingLeft - event.clientX, 2))) + 'px';
$('span').text('From your starting point(22x10) you moved: ' + math);
});
Came up with the something similiar to Sergio, but this will calculate disatance from the point the mouse has been held down, and like jfriend said the distance between two points,
d = ( (x1-x2)^2 + (y1-y2)^2 )^(1/2)
var totalMovement = 0;
var lastX = -1;
var lastY = -1;
var startX = -1;
var startY = -1;
$(document).mousemove(function(event) {
if (startX == -1) {
return;
}
if (startY == -1) {
return;
}
totalMovement += Math.sqrt(Math.pow(lastY - event.clientY, 2) + Math.pow(lastX - event.clientX, 2));
$('span').text('From your starting point (' + startX + 'x' + startY + ') you moved: ' + totalMovement);
lastX = event.clientX;
lastY = event.clientY;
});
$(document).mousedown(function(event) {
startX = event.clientX;
startY = event.clientY;
lastX = event.clientX;
lastY = event.clientY;
});
$(document).mouseup(function(event) {
startX = -1;
startY = -1;
totalMovement = 0;
lastX = 0;
lastY = 0;
});

Categories