How to get the mouse position without events (without moving the mouse)?

255,078

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...

Share:
255,078
Norbert Tamas
Author by

Norbert Tamas

http://www.linkedin.com/in/norberttamas/

Updated on August 27, 2021

Comments

  • Norbert Tamas
    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
    Pointy about 14 years
    ha ha - at some point you should google around and see if you can figure out how many people have actually implemented this
  • machineaddict
    machineaddict almost 12 years
    Actually, 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
    Paul Hiemstra over 11 years
    Doesn't this still require the user to move the mouse?
  • jake
    jake over 11 years
    Did 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
    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
    Darius Bacon about 11 years
    Perhaps 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
    Darius Bacon about 11 years
    stackoverflow.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
    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
    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
    Mark K Cowan almost 10 years
    You 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
    Peter Hansen over 9 years
    This 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
    Mariano Desanze about 9 years
    In 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
    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
    trinalbadger587 about 9 years
    I think that I can just wait until the mouse moves once and not set the CPU on fire.
  • timetowonder
    timetowonder over 8 years
    Although 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
    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
    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
    polkovnikov.ph over 8 years
    I don't see why this gets upvoted at all, when there's a real answer in this same topic.
  • Tim Down
    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
    SuperUberDuper almost 8 years
    very few users wont fire mouse events
  • rtpax
    rtpax over 7 years
    A potentially useful addition is to add a function for the mouseleave event that sets x and y back to null or 'undefined'
  • KRB
    KRB over 7 years
    Careful, 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
    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
    tresf over 6 years
    For me, it returns undefined regardless. Can you elaborate as how to use this?
  • StefansArya
    StefansArya over 6 years
    It 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
    tresf over 6 years
    Thanks. 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
    junvar almost 6 years
    chrome 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
    SuperNova almost 6 years
    It 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
    Salman von Abbas almost 6 years
    Doesn't work. I just tested on a blank page in Chrome, Firefox and Edge. Neither mouseenter nor mousemove 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
    Swap-IOS-Android over 5 years
    I 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
    kevzettler over 5 years
    any links to back up @KRB claim?
  • Jacksonkr
    Jacksonkr over 5 years
    This 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
    Paul Feakins over 4 years
    As 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
    SuperNova over 4 years
    The browser vendors seem to have this patched out. My answer is from 2014 and it worked several years.
  • trusktr
    trusktr over 4 years
    apparently these tricks no longer work unless there is an explicit mouse move by the user. :(
  • mmonteirocl
    mmonteirocl over 3 years
    Yes but only the first move. Then when its moved once we know already the px X Y
  • gillonba
    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
    Pointy over 3 years
    @gillonba this is essentially an impractical joke answer to the question, and it's from 11 years ago.