How to get the mouse position without events (without moving the mouse)?
Solution 1
Real answer: No, it's not possible.
OK, I have just thought of a way. Overlay your page with a div that covers the whole document. Inside that, create (say) 2,000 x 2,000 <a>
elements (so that the :hover
pseudo-class will work in IE 6, see), each 1 pixel in size. Create a CSS :hover
rule for those <a>
elements that changes a property (let's say font-family
). In your load handler, cycle through each of the 4 million <a>
elements, checking currentStyle
/ getComputedStyle()
until you find the one with the hover font. Extrapolate back from this element to get the co-ordinates within the document.
N.B. DON'T DO THIS.
Solution 2
Edit 2020: This does not work any more. It seems so, that the browser vendors patched this out. Because the most browsers rely on chromium, it might be in its core.
Old answer: You can also hook mouseenter (this event is fired after page reload, when the mousecursor is inside the page). Extending Corrupted's code should do the trick:
var x = null;
var y = null;
document.addEventListener('mousemove', onMouseUpdate, false);
document.addEventListener('mouseenter', onMouseUpdate, false);
function onMouseUpdate(e) {
x = e.pageX;
y = e.pageY;
console.log(x, y);
}
function getMouseX() {
return x;
}
function getMouseY() {
return y;
}
You can also set x and y to null on mouseleave-event. So you can check if the user is on your page with it's cursor.
Solution 3
What you can do is create variables for the x
and y
coordinates of your cursor, update them whenever the mouse moves and call a function on an interval to do what you need with the stored position.
The downside to this of course is that at least one initial movement of the mouse is required to have it work. As long as the cursor updates its position at least once, we are able to find its position regardless of whether it moves again.
var cursor_x = -1;
var cursor_y = -1;
document.onmousemove = function(event)
{
cursor_x = event.pageX;
cursor_y = event.pageY;
}
setInterval(check_cursor, 1000);
function check_cursor(){console.log('Cursor at: '+cursor_x+', '+cursor_y);}
The preceding code updates once a second with a message of where your cursor is. I hope this helps.
Solution 4
@Tim Down's answer is not performant if you render 2,000 x 2,000 <a>
elements:
OK, I have just thought of a way. Overlay your page with a div that covers the whole document. Inside that, create (say) 2,000 x 2,000 elements (so that the :hover pseudo-class will work in IE 6, see), each 1 pixel in size. Create a CSS :hover rule for those elements that changes a property (let's say font-family). In your load handler, cycle through each of the 4 million elements, checking currentStyle / getComputedStyle() until you find the one with the hover font. Extrapolate back from this element to get the co-ordinates within the document.
N.B. DON'T DO THIS.
But you don't have to render 4 million elements at once, instead use binary search. Just use 4 <a>
elements instead:
- Step 1: Consider the whole screen as the starting search area
- Step 2: Split the search area into 2 x 2 = 4 rectangle
<a>
elements - Step 3: Using the
getComputedStyle()
function determine in which rectangle mouse hovers - Step 4: Reduce the search area to that rectangle and repeat from step 2.
This way you would need to repeat these steps max 11 times, considering your screen is not wider than 2048px.
So you will generate max 11 x 4 = 44 <a>
elements.
If you don't need to determine the mouse position exactly to a pixel, but say 10px precision is OK. You would repeat the steps at most 8 times, so you would need to draw max 8 x 4 = 32 <a>
elements.
Also generating and then destroying the <a>
elements is not performat as DOM is generally slow. Instead, you can just reuse the initial 4 <a>
elements and just adjust their top
, left
, width
and height
as you loop through steps.
Now, creating 4 <a>
is an overkill as well. Instead, you can reuse the same one <a>
element for when testing for getComputedStyle()
in each rectangle. So, instead of splitting the search area into 2 x 2 <a>
elements just reuse a single <a>
element by moving it with top
and left
style properties.
So, all you need is a single <a>
element change its width
and height
max 11 times, and change its top
and left
max 44 times and you will have the exact mouse position.
Solution 5
You could try something similar to what Tim Down suggested - but instead of having elements for each pixel on the screen, create just 2-4 elements (boxes), and change their location, width, height dynamically to divide the yet possible locations on screen by 2-4 recursively, thus finding the mouse real location quickly.
For example - first elements take right and left half of screen, afterwards the upper and lower half. By now we already know in which quarter of screen the mouse is located, are able to repeat - discover which quarter of this space...
Comments
-
Norbert Tamas almost 3 years
Is it possible to get the mouse position with JavaScript after page loads without any mouse movement event (without moving the mouse)?
-
Pointy about 14 yearsha ha - at some point you should google around and see if you can figure out how many people have actually implemented this
-
machineaddict almost 12 yearsActually, it is implementable without having to much CPU load (I think. I haven't been testing it). On dom ready build the <a> elements with javascript, take the mouse postion and then remove all <a> elements. On mousemouse you should have other function to take the mouse position. Anyway, this was hilarious.
-
Paul Hiemstra over 11 yearsDoesn't this still require the user to move the mouse?
-
jake over 11 yearsDid you read the subject of this post? The OP asks how to get the mouse coordinates without using an event. Yet your post suggests using the onmousemove event.
-
jpeltoniemi about 11 years@jake Although the OP specifically asked for a non-event method, this answer benefits others who came here looking for an answer and possibly a workaround. Also, I'd consider this answer partially within topic since as far as I know, this is the best method to get the cursor position at any given time without having to use events directly. That said, the answer could've been worded more along the lines of stating the fact and offering a way around to avoid nitpicking in comments.
-
Darius Bacon about 11 yearsPerhaps this could be made practical with binary search? Loop making a pair of
<a>
elements covering given rectangles (using absolute positioning of sized<img>
elements, I suppose), shrinking the rectangles each time. Yes, it's ridiculous, but so is not being able to get this info before the first mousemove. -
Darius Bacon about 11 yearsstackoverflow.com/a/8543879/27024 says the hover doesn't fire either until the mouse moves for the first time. This foils this scheme.
-
Tim Down about 11 years@DariusBacon: That linked answer doesn't seem to be correct: jsbin.com/utocax/3. So yes, this approach may be practical for some situations.
-
Jaak Kütt about 10 years@TimDown a small part of me hoped to see 4 mil <a> elements while the jsbin example page was loading :D
-
Mark K Cowan almost 10 yearsYou could implement this much more efficiently by using divide-and-conquer, e.g. a binary search. You only need two <a> elements then.
-
Peter Hansen over 9 yearsThis would seem to be the only truly useful answer here, which seems odd. Indeed (in latest Firefox, Chrome and IE11) the mouseenter fires on page load and provides the correct coordinates. Has browser behaviour in this area simply changed in the last few years?
-
Mariano Desanze about 9 yearsIn fact "mouseenter" doesn't seem to add any value. I tested with the following jsfiddle in Chrome and IE, and they don't show the cordinates until you put the mouse on the inner document (the result panel): jsfiddle.net/xkpd784o/1
-
SuperNova about 9 years@Proton: Move your mouse to the result panel to the area of the resultpanel BEFORE page has fully loaded and don't move than. After onload the page immediatly knows the position of the mouse. No mouse movement is needed. So mouseenter is also fired, when the page has loaded and the mouse is inside the document area. That is, what the OP originally wanted. No one other provides this answer.
-
trinalbadger587 about 9 yearsI think that I can just wait until the mouse moves once and not set the CPU on fire.
-
timetowonder over 8 yearsAlthough this funny solution sounds like something that is ridiculous but working, it's not actually a working solution. It has the same problem which was there in the first place: hover events do not occur when the mouse doesn't move. You can cover your page in "hoverable" elements all you want, and they still won't be hovered upon page refresh until the mouse moves. But then you could simply respond to the mousemove event.
-
Tim Down over 8 years@timetowonder: I'm not sure that's always been entirely true in all browsers and operating systems. I'm pretty sure I had a simple example working in at least one browser at one time.
-
polkovnikov.ph over 8 years@Pichan It didn't benefit me, because I've been looking for a way to fill those
cursorX/Y
variable before any event happens. -
polkovnikov.ph over 8 yearsI don't see why this gets upvoted at all, when there's a real answer in this same topic.
-
Tim Down over 8 years@polkovnikov.ph When I wrote this, there wasn't a real answer and if the "real answer" works then browser behaviour has changed since then. However, I do agree that this shouldn't be the accepted answer.
-
SuperUberDuper almost 8 yearsvery few users wont fire mouse events
-
rtpax over 7 yearsA potentially useful addition is to add a function for the
mouseleave
event that setsx
andy
back tonull
or'undefined'
-
KRB over 7 yearsCareful, it can be costly to keep an mousemove listener around. I would suggest recreating the listener in the interval and destroying the listener after you get coordinates.
-
SuperNova about 7 years@brillout.com I've just tested it in Chrome 57 under windows: Works like a charm. What did not work in your test?
-
tresf over 6 yearsFor me, it returns
undefined
regardless. Can you elaborate as how to use this? -
StefansArya over 6 yearsIt would return
undefined
when the cursor wasn't hovering any element (or when the browser lost focus). You may need to set a time interval if you're testing from the console.. -
tresf over 6 yearsThanks.
setTimeout
worked. I was using jsfiddle and you're right, it never hit a hover event because it redraws the DOM each time you click play. I would recommend adding this hint for others. -
junvar almost 6 yearschrome 68, using the jsfiddel above, alert occurs on first mouse move and not on load, even if mouse is moved to the rendered region before the page finished loading.
-
SuperNova almost 6 yearsIt seems to be a problem with the fiddle (now) or the used iframes on jsfiddle. Putting the code into a blank html file running local or via http is working like a charm for me (chrome 68)
-
Salman von Abbas almost 6 yearsDoesn't work. I just tested on a blank page in Chrome, Firefox and Edge. Neither
mouseenter
normousemove
fire on page load even if the cursor is inside the page. See my answer for a better solution: stackoverflow.com/a/52141050/362006 -
Swap-IOS-Android over 5 yearsI do not want accurate mouse position but i just want to know that mouse is extreme right or extreme left into function without event object so your solution works in my case..thank you
-
kevzettler over 5 yearsany links to back up @KRB claim?
-
Jacksonkr over 5 yearsThis is kind of amazing as it's a clear edge case for SOF. On one hand you have a clearly thoughtful answer that feasibly worked at the time of writing, which [outdated answers] are part of the nature of the historical data in general. On the other hand this "solution" is a total hack while fully encompassing the purest spirit of ingenuity and ingenuity is core to SOF! I want to see answers like this stay and I second (or third at this point) that this needn't be the accepted answer.
-
Paul Feakins over 4 yearsAs above, I've done various tests in Firefox and Chrome and this doesn't work on refresh, although it does work in Chrome after refresh on mouse move, but that's not what we want.
-
SuperNova over 4 yearsThe browser vendors seem to have this patched out. My answer is from 2014 and it worked several years.
-
trusktr over 4 yearsapparently these tricks no longer work unless there is an explicit mouse move by the user. :(
-
mmonteirocl over 3 yearsYes but only the first move. Then when its moved once we know already the px X Y
-
gillonba over 3 years@Pointy maybe you should share one of those links for people who did google around and found this question at the top of their search results
-
Pointy over 3 years@gillonba this is essentially an impractical joke answer to the question, and it's from 11 years ago.