I have this design and works perfectly: http://jsfiddle.net/98Bgq/22/
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
var scrollX = $canvas.scrollLeft();
var scrollY = $canvas.scrollTop();
But when I resize the screen of my browser, it seems the canvas begins to operate in a totally different way than normal, in the above example can not I click a few more parts of the design, how can I solve this?
Since you're using jQuery, it will probably be easiest to use event.pageX. E.g.
mouseX = e.pageX - $canvas.offset().left;
mouseY = e.pageY - $canvas.offset().top;
Edit: For non-jQuery, this works well:
mouseX = e.hasOwnProperty('offsetX') ? e.offsetX : e.layerX;
mouseY = e.hasOwnProperty('offsetY') ? e.offsetY : e.layerY;
event.pageY/X returns the mouse position relative to the top/left edge of the document. $elmnt.offset() returns the coordinates of the element relative to the document. So subtracting the latter from the former gives you the relative position of the mouse in the canvas.
event.offsetY/X/event.layerY/X give you the coordinate of the event relative to the current layer. layerX doesn't work with chrome, so if it's not present, offsetX is used instead.
offset and scroll might change on a window resize : handle the resize event and recompute them :
this fiddle seems to work :
http://jsfiddle.net/gamealchemist/98Bgq/24/
code :
var offsetX = 0, offsetY = 0;
var scrollX = 0, scrollY = 0;
function computeOffset() {
canvasOffset = $canvas.offset();
offsetX = canvasOffset.left;
offsetY = canvasOffset.top;
scrollX = $canvas.scrollLeft();
scrollY = $canvas.scrollTop();
}
computeOffset();
window.onresize = computeOffset;
Related
I'm trying to create a simple animation where some particles animation follow the cursor, but i'm having trouble with it.
I've created a fiddle to replicate the issue : Example on JSFiddle
Right now my particles appear, but when you move the cursor over the section, they suddenly disappear. I know my error comes from my mousemove() function, but i can't figure out what is wrong with it..
here is my mousemove function :
function mouseMove(e) {
var posx = posy = 0;
if (e.pageX || e.pageY) {
posx = e.pageX;
posy = e.pageY;
}
else if (e.clientX || e.clientY) {
posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
}
target.x = posx;
target.y = posy;
}
Your mouse coordinate X, Y is relative to the top/left corner of the web page, probably mousemove event is attached to document, not to the canvas. Attach the mosemove event to the canvas
document.getElementById('services-canvas').addEventListener('mousemove', mouseMove);
And use the elemnt ofset:
target.x = e.offsetX;
target.y = e.offsetY;
If you would like the mouse to be in the centre of figure, then use e.offsetY-something where something is half of height of figure
So your particles do actually follow the mouse from what I have seen in . However, it seems that they are way lower in the y position that you would expect.You need to do this to make it work properly:
target.y = posy -300;
I have tried it and it worked with this little change. Hope this helped :D
I am trying to drag and drop a element based on mouse coordinates. Its working fine in chrome and IE but not working in firefox.
Below is what I have tried:
function createShape(event)
{
var stageContainer = $(".mainArea");
var stageOffset = stageContainer.offset();
clientX = event.clientX;
clientY = event.clientY;
offsetX = stageOffset.left;
offsetY = stageOffset.top;
x = clientX - offsetX; // works in chrome and IE
y = clientY - offsetY; // works in chrome and IE
//Firefox
var offX = (event.offsetX || event.pageX - $(event.target).offset().left);
var offY = (event.offsetY || event.pageY - $(event.target).offset().top);
layerX = event.layerX;
layerY = event.layerX;
screenX = event.screenX;
screenY = event.screenY;
pageX = event.pageX;
pageY = event.pageY;
e = jQuery.event.fix(event);
var target = event.target || event.srcElement;
//Right now this is working but x and y are not exactly correct
x = screenX + offsetX
y = screenY + offsetY
Doesn't work in firefox
ClientXY return 0,0
LayerXY return largest number like 173839,173839
pageX and pageY returns 0,0
element.offset().left returns 70 always
element.offset().top returns 63 always
createRect(x, y); // creating element on dragend with x and y coordinates on dragend
}
How do I get drag end mouse coordinates?
Sadly, Firefox does not fill pageX and pageY properties on drag events. The relevant bug report is open since 2009 and it doesn't look like it is getting fixed anytime soon. The common solution is to listen for dragover event on the parent element (although it makes it difficult to detect which element is being dragged) or detect the position of the element being dragged in some other way.
I am trying to use canvas so that with a mouse a person can write their signature. Everything works until I stretch or scroll the screen then it draws the line in a different place away from the mouse.
The Code:
function onMouseUp(event) {
'use strict';
mousePressed = false;
}
function onMouseMove(event) {
'use strict';
if (mousePressed) {
event.preventDefault();
mouseX = event.clientX - can.offsetLeft - mleft;
mouseY = event.clientY - can.offsetTop - mtop;
ctx.lineTo(mouseX, mouseY);
ctx.stroke();
}
}
function onMouseDown(event) {
'use strict';
mousePressed = true;
mouseX = event.clientX - can.offsetLeft - mleft;
mouseY = event.clientY - can.offsetTop - mtop;
ctx.beginPath();
ctx.moveTo(mouseX, mouseY);
}
can.addEventListener('mousemove', onMouseMove, false);
can.addEventListener('mousedown', onMouseDown, false);
can.addEventListener('mouseup', onMouseUp, false);
HTML looks like:
<canvas id="signature" width="567" height="150"></canvas>
event.clientX/Y is relative to the top left corner of the viewport. So scroll isn't taken into account. event.pageX/Y is relative to the document. So it is the position on screen that the event happened including scroll. You can change all references to clientX to pageX and clientY to pageY and it should work.
Explanation of each screen/page/client XY.
It seems like you just need a more reliable method of getting the relative coordinates when the page reflows.
#RyanArtecona wrote the following function in response to this question about mouse coordinates relative to a canvas:
function relMouseCoords(event){
var totalOffsetX = 0;
var totalOffsetY = 0;
var canvasX = 0;
var canvasY = 0;
var currentElement = this;
do{
totalOffsetX += currentElement.offsetLeft - currentElement.scrollLeft;
totalOffsetY += currentElement.offsetTop - currentElement.scrollTop;
}
while(currentElement = currentElement.offsetParent)
canvasX = event.pageX - totalOffsetX;
canvasY = event.pageY - totalOffsetY;
return {x:canvasX, y:canvasY}
}
HTMLCanvasElement.prototype.relMouseCoords = relMouseCoords;
This is convenient because it adds a function to get the relative coordinates right onto the prototype of the HTMLCanvasElement function, which means you can just pass in a reference to the canvas you want to use, and get coordinates relative to it.
Using this you could rewrite your mousedown function (and you'll want to do the others as well, but just for an example) as follows:
function onMouseDown(event) {
'use strict';
mousePressed = true;
// get a reference to the 'signature' canvas
var canvas = document.getElementById('signature');
// this returns an object with 'x' and 'y' properties
var mouse = canvas.relMouseCoords(event)
ctx.beginPath();
// use the coordinates you got
ctx.moveTo(mouse.x, mouse.y);
}
Change these two lines
mouseX = event.clientX - can.offsetLeft - mleft;
mouseY = event.clientY - can.offsetTop - mtop;
to
mouseX = event.offsetX || event.layerX;
mouseY = event.offsetY || event.layerY;
in both of your handlers. The browser can handle the relative coordinates for you without having to do any special math. offsetX/Y seems Chrome/IE specific and layerX/Y gets you Firefox support.
Here is a jsfiddle. I made a couple slight declaration changes to get your use stricts to work, since we seem to be missing a little of the code.
Add the scroll offset of the screen to the mouseX and mouseY. with jQuery it would look like this
mouseX = event.clientX - can.offsetLeft - mleft + $(window).scrollLeft;
mouseY = event.clientY - can.offsetTop - mtop + $(window).scrollTop;
This is not a simple answer. The best way to figure this out is to start with a good foundation and then make incremental changes for your situation.. The best article I have seen on this subject is from the Internet Explorer Team:
Handling Multi-touch and Mouse Input in All Browsers
This article will give you a great foundation to capturing mouse input correctly.
I'm working with this script "Drawing polygons with the mouse" and it works very well.
The issue I have is when I put the canvas in the design of my site. The canvas is thus now in relative position and the coords are wrong. I have a lag between my cursor and the draw…
If I set the div in position: fixed, there is no problem.
The positions are declared as follows:
canvas.addEventListener("click", function(e) {
var x = e.clientX-canvas.offsetLeft;
var y = e.clientY-canvas.offsetTop;
How to fix this? How to put the canvas in my design and have the right coords?
Thank you very much!
Try my "simple" mouse code (simple because it does not take into account border/padding/HTML offset):
function getMouse(e, canvas) {
var element = canvas, offsetX = 0, offsetY = 0, mx, my;
// Compute the total offset
if (element.offsetParent !== undefined) {
do {
offsetX += element.offsetLeft;
offsetY += element.offsetTop;
} while ((element = element.offsetParent));
}
// This isn't the best code because I am not adding padding and border style widths to offset. I'm just keeping it simple.
mx = e.pageX - offsetX;
my = e.pageY - offsetY;
return {x: mx, y: my};
}
This question already has answers here:
How do I get the coordinates of a mouse click on a canvas element? [duplicate]
(22 answers)
Closed 3 years ago.
Is there a way to get the location mouse inside a <canvas> tag? I want the location relative to to the upper right corner of the <canvas>, not the entire page.
The accepted answer will not work every time. If you don't use relative position the attributes offsetX and offsetY can be misleading.
You should use the function: canvas.getBoundingClientRect() from the canvas API.
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
canvas.addEventListener('mousemove', function(evt) {
var mousePos = getMousePos(canvas, evt);
console.log('Mouse position: ' + mousePos.x + ',' + mousePos.y);
}, false);
Easiest way is probably to add a onmousemove event listener to the canvas element, and then you can get the coordinates relative to the canvas from the event itself.
This is trivial to accomplish if you only need to support specific browsers, but there are differences between f.ex. Opera and Firefox.
Something like this should work for those two:
function mouseMove(e)
{
var mouseX, mouseY;
if(e.offsetX) {
mouseX = e.offsetX;
mouseY = e.offsetY;
}
else if(e.layerX) {
mouseX = e.layerX;
mouseY = e.layerY;
}
/* do something with mouseX/mouseY */
}
Also note that you'll need CSS:
position: relative;
set to your canvas tag, in order to get the relative mouse position inside the canvas.
And the offset changes if there's a border
I'll share the most bulletproof mouse code that I have created thus far. It works on all browsers will all manner of padding, margin, border, and add-ons (like the stumbleupon top bar)
// Creates an object with x and y defined,
// set to the mouse position relative to the state's canvas
// If you wanna be super-correct this can be tricky,
// we have to worry about padding and borders
// takes an event and a reference to the canvas
function getMouse = function(e, canvas) {
var element = canvas, offsetX = 0, offsetY = 0, mx, my;
// Compute the total offset. It's possible to cache this if you want
if (element.offsetParent !== undefined) {
do {
offsetX += element.offsetLeft;
offsetY += element.offsetTop;
} while ((element = element.offsetParent));
}
// Add padding and border style widths to offset
// Also add the <html> offsets in case there's a position:fixed bar (like the stumbleupon bar)
// This part is not strictly necessary, it depends on your styling
offsetX += stylePaddingLeft + styleBorderLeft + htmlLeft;
offsetY += stylePaddingTop + styleBorderTop + htmlTop;
mx = e.pageX - offsetX;
my = e.pageY - offsetY;
// We return a simple javascript object with x and y defined
return {x: mx, y: my};
}
You'll notice that I use some (optional) variables that are undefined in the function. They are:
stylePaddingLeft = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingLeft'], 10) || 0;
stylePaddingTop = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingTop'], 10) || 0;
styleBorderLeft = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderLeftWidth'], 10) || 0;
styleBorderTop = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderTopWidth'], 10) || 0;
// Some pages have fixed-position bars (like the stumbleupon bar) at the top or left of the page
// They will mess up mouse coordinates and this fixes that
var html = document.body.parentNode;
htmlTop = html.offsetTop;
htmlLeft = html.offsetLeft;
I'd recommend only computing those once, which is why they are not in the getMouse function.
For mouse position, I usually use jQuery since it normalizes some of the event attributes.
function getPosition(e) {
//this section is from http://www.quirksmode.org/js/events_properties.html
var targ;
if (!e)
e = window.event;
if (e.target)
targ = e.target;
else if (e.srcElement)
targ = e.srcElement;
if (targ.nodeType == 3) // defeat Safari bug
targ = targ.parentNode;
// jQuery normalizes the pageX and pageY
// pageX,Y are the mouse positions relative to the document
// offset() returns the position of the element relative to the document
var x = e.pageX - $(targ).offset().left;
var y = e.pageY - $(targ).offset().top;
return {"x": x, "y": y};
};
// now just make sure you use this with jQuery
// obviously you can use other events other than click
$(elm).click(function(event) {
// jQuery would normalize the event
position = getPosition(event);
//now you can use the x and y positions
alert("X: " + position.x + " Y: " + position.y);
});
This works for me in all the browsers.
EDIT:
I copied the code from one of my classes I was using, so the jQuery call to this.canvas was wrong. The updated function figures out which DOM element (targ) caused the event and then uses that element's offset to figure out the correct position.
GEE is an endlessly helpful library for smoothing out troubles with canvas, including mouse location.
Simple approach using mouse event and canvas properties:
JSFiddle demo of functionality http://jsfiddle.net/Dwqy7/5/
(Note: borders are not accounted for, resulting in off-by-one):
Add a mouse event to your canvas
canvas.addEventListener("mousemove", mouseMoved);
Adjust event.clientX and event.clientY based on:
canvas.offsetLeft
window.pageXOffset
window.pageYOffset
canvas.offsetTop
Thus:
canvasMouseX = event.clientX - (canvas.offsetLeft - window.pageXOffset);
canvasMouseY = event.clientY - (canvas.offsetTop - window.pageYOffset);
The original question asked for coordinates from the upper right (second function).
These functions will need to be within a scope where they can access the canvas element.
0,0 at upper left:
function mouseMoved(event){
var canvasMouseX = event.clientX - (canvas.offsetLeft - window.pageXOffset);
var canvasMouseY = event.clientY - (canvas.offsetTop - window.pageYOffset);
}
0,0 at upper right:
function mouseMoved(event){
var canvasMouseX = canvas.width - (event.clientX - canvas.offsetLeft)- window.pageXOffset;
var canvasMouseY = event.clientY - (canvas.offsetTop - window.pageYOffset);
}
I'd use jQuery.
$(document).ready(function() {
$("#canvas_id").bind( "mousedown", function(e){ canvasClick(e); } );
}
function canvasClick( e ){
var x = e.offsetX;
var y = e.offsetY;
}
This way your canvas can be anywhere on your page, relative or absolute.
Subtract the X and Y offsets of the canvas DOM element from the mouse position to get the local position inside the canvas.