240

I am hoping to track the position of the mouse cursor, periodically every t mseconds. So essentially, when a page loads - this tracker should start and for (say) every 100 ms, I should get the new value of posX and posY and print it out in the form.

I tried the following code - but the values do not get refreshed - only the initial values of posX and posY show up in the form boxes. Any ideas on how I can get this up and running ?

<html>
<head>
<title> Track Mouse </title>
<script type="text/javascript">
function mouse_position()
{
    var e = window.event;

    var posX = e.clientX;
    var posY = e.clientY;

    document.Form1.posx.value = posX;
    document.Form1.posy.value = posY;

    var t = setTimeout(mouse_position,100);

}
</script>

</head>

<body onload="mouse_position()">
<form name="Form1">
POSX: <input type="text" name="posx"><br>
POSY: <input type="text" name="posy"><br>
</form>
</body>
</html>
coolaj86
  • 74,004
  • 20
  • 105
  • 125
Hari
  • 5,057
  • 9
  • 41
  • 51
  • The problem is that there will be no `event` object when the function is called for the second time. You probably should listen to some event than use `setTimeout`. – Felix Kling Oct 17 '11 at 07:47
  • Yes, but shouldn't the mouse_position() function keep calling itself every 100 milliseconds. Shouldn't it actually behave like an infinite recursive function ? – Hari Oct 17 '11 at 07:49
  • 2
    possible duplicate of [capture mouse position on setInterval() in Javascript](http://stackoverflow.com/questions/1608498/capture-mouse-position-on-setinterval-in-javascript) – Shadow The GPT Wizard Oct 17 '11 at 07:51
  • @Titan: Yes, but I suspect that it will error because `window.event` will be `undefined` or `null`. If there is no event, there is no `event` object. – Felix Kling Oct 17 '11 at 07:51

19 Answers19

244

The mouse's position is reported on the event object received by a handler for the mousemove event, which you can attach to the window (the event bubbles):

(function() {
    document.onmousemove = handleMouseMove;
    function handleMouseMove(event) {
        var eventDoc, doc, body;

        event = event || window.event; // IE-ism

        // If pageX/Y aren't available and clientX/Y are,
        // calculate pageX/Y - logic taken from jQuery.
        // (This is to support old IE)
        if (event.pageX == null && event.clientX != null) {
            eventDoc = (event.target && event.target.ownerDocument) || document;
            doc = eventDoc.documentElement;
            body = eventDoc.body;

            event.pageX = event.clientX +
              (doc && doc.scrollLeft || body && body.scrollLeft || 0) -
              (doc && doc.clientLeft || body && body.clientLeft || 0);
            event.pageY = event.clientY +
              (doc && doc.scrollTop  || body && body.scrollTop  || 0) -
              (doc && doc.clientTop  || body && body.clientTop  || 0 );
        }

        // Use event.pageX / event.pageY here
    }
})();

(Note that the body of that if will only run on old IE.)

Example of the above in action - it draws dots as you drag your mouse over the page. (Tested on IE8, IE11, Firefox 30, Chrome 38.)

If you really need a timer-based solution, you combine this with some state variables:

(function() {
    var mousePos;

    document.onmousemove = handleMouseMove;
    setInterval(getMousePosition, 100); // setInterval repeats every X ms

    function handleMouseMove(event) {
        var dot, eventDoc, doc, body, pageX, pageY;

        event = event || window.event; // IE-ism

        // If pageX/Y aren't available and clientX/Y are,
        // calculate pageX/Y - logic taken from jQuery.
        // (This is to support old IE)
        if (event.pageX == null && event.clientX != null) {
            eventDoc = (event.target && event.target.ownerDocument) || document;
            doc = eventDoc.documentElement;
            body = eventDoc.body;

            event.pageX = event.clientX +
              (doc && doc.scrollLeft || body && body.scrollLeft || 0) -
              (doc && doc.clientLeft || body && body.clientLeft || 0);
            event.pageY = event.clientY +
              (doc && doc.scrollTop  || body && body.scrollTop  || 0) -
              (doc && doc.clientTop  || body && body.clientTop  || 0 );
        }

        mousePos = {
            x: event.pageX,
            y: event.pageY
        };
    }
    function getMousePosition() {
        var pos = mousePos;
        if (!pos) {
            // We haven't seen any movement yet
        }
        else {
            // Use pos.x and pos.y
        }
    }
})();

As far as I'm aware, you can't get the mouse position without having seen an event, something which this answer to another Stack Overflow question seems to confirm.

Side note: If you're going to do something every 100ms (10 times/second), try to keep the actual processing you do in that function very, very limited. That's a lot of work for the browser, particularly older Microsoft ones. Yes, on modern computers it doesn't seem like much, but there is a lot going on in browsers... So for example, you might keep track of the last position you processed and bail from the handler immediately if the position hasn't changed.

Martijn
  • 15,791
  • 4
  • 36
  • 68
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Now it's as good as safe to use pageX/Y, clientX/Y and screenX/Y. The IE will be soon forgotten, so it's much simpler than this. – Martin Braun Jan 18 '21 at 21:32
125
onmousemove = function(e){console.log("mouse location:", e.clientX, e.clientY)}

Open your console (Ctrl+Shift+J), copy-paste the code above and move your mouse on browser window.

shA.t
  • 16,580
  • 5
  • 54
  • 111
RegarBoy
  • 3,228
  • 1
  • 23
  • 44
74

Here's a solution, based on jQuery and a mouse event listener (which is far better than a regular polling) on the body:

$("body").mousemove(function(e) {
    document.Form1.posx.value = e.pageX;
    document.Form1.posy.value = e.pageY;
})
solendil
  • 8,432
  • 4
  • 28
  • 29
  • As I had mentioned, the regular polling is exactly what I want to do. I am not tracking changes in mouse events, I am only looking to capture the mouse position every x milliseconds (irrespective of whether the mouse moved or not). – Hari Oct 17 '11 at 07:53
  • 3
    Why tracking a value that you know for sure didn't change? I don't understand, unless it is a homework problem. With the event method, you can track every change of these values, then do a 100ms polling elsewhere if you need to handle these values for whatever purpose. – solendil Oct 17 '11 at 07:57
  • 1
    There's not advantage of using jQuery here except unnecessarily using a 5mb JS lib – Pattycake Jr Apr 05 '19 at 21:38
  • @PattycakeJr The last time I looked it was under 90kB in the minified version – Kris May 09 '19 at 15:33
  • 2
    @PattycakeJr also if you're *super* unlikely downloading it at all if you point to a CDN since almost every other site links to it – Brian Leishman Jun 06 '19 at 22:10
16

What I think that he only wants to know the X/Y positions of cursor than why answer is that complicated.

// Getting 'Info' div in js hands
var info = document.getElementById('info');

// Creating function that will tell the position of cursor
// PageX and PageY will getting position values and show them in P
function tellPos(p){
  info.innerHTML = 'Position X : ' + p.pageX + '<br />Position Y : ' + p.pageY;
}
addEventListener('mousemove', tellPos, false);
* {
  padding: 0:
  margin: 0;
  /*transition: 0.2s all ease;*/
  }
#info {
  position: absolute;
  top: 10px;
  right: 10px;
  background-color: black;
  color: white;
  padding: 25px 50px;
}
<!DOCTYPE html>
<html>
  
  <body>
    <div id='info'></div>
        </body>
  </html>
Murtaza
  • 283
  • 2
  • 9
14

I believe that we are overthinking this,

function mouse_position(e)
{
//do stuff
}
<body onmousemove="mouse_position(event)"></body>
dGRAMOP
  • 753
  • 5
  • 19
  • 1
    Im new to this forum, so just so I know, please explain why you -1nd my awnser - this is so I dont make the same mistake again. Thanks! ThePROgrammer – dGRAMOP Mar 21 '15 at 15:12
  • 10
    I too get annoyed by downvotes with no explanation. To give you a possible explanation, this answer doesn't address the OP's problem of polling every 100 ms. It is clearer in his response to other answers that this is a necessity. – aaaaaa Apr 16 '15 at 09:18
  • 1
    also this sort of inline event handling is deprecated I believe. `document.body.addEventListener("mousemove", function (e) {})` is the way to do this, in your javascript code as opposed to in the html – Ryan Jul 31 '19 at 21:49
9

ES6 based code:

let handleMousemove = (event) => {
  console.log(`mouse position: ${event.x}:${event.y}`);
};

document.addEventListener('mousemove', handleMousemove);

If you need throttling for mousemoving, use this:

let handleMousemove = (event) => {
  console.warn(`${event.x}:${event.y}\n`);
};

let throttle = (func, delay) => {
  let prev = Date.now() - delay;
  return (...args) => {
    let current = Date.now();
    if (current - prev >= delay) {
      prev = current;
      func.apply(null, args);
    }
  }
};

// let's handle mousemoving every 500ms only
document.addEventListener('mousemove', throttle(handleMousemove, 500));

here is example

Grant Winney
  • 65,241
  • 13
  • 115
  • 165
oboshto
  • 3,478
  • 4
  • 25
  • 24
8

Just a simplified version of @T.J. Crowder and @RegarBoy's answers.

Less is more in my opinion.

Check out onmousemove event for more info about the event.

Image mouse tracker

There's a new value of posX and posY every time the mouse moves according to the horizontal and vertical coordinates.

<!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <title>Example Mouse Tracker</title>
      <style>    
        body {height: 3000px;}
        .dot {width: 2px;height: 2px;background-color: black;position: absolute;}
      </style>
    </head>
    <body>
    <p>Mouse tracker</p>
    <script>
    onmousemove = function(e){
        //Logging purposes
        console.log("mouse location:", e.clientX, e.clientY);

        //meat and potatoes of the snippet
        var pos = e;
        var dot;
        dot = document.createElement('div');
        dot.className = "dot";
        dot.style.left = pos.x + "px";
        dot.style.top = pos.y + "px";
        document.body.appendChild(dot);
    }      
    </script>
    </body>
    </html>
NetVicious
  • 3,848
  • 1
  • 33
  • 47
Jonas
  • 1,105
  • 1
  • 15
  • 21
  • good job, do you have some tips to make more point when we move mouse fast ? Faster are movement, bigest is the gap between 2 points. Possible to reduce it ? – Matrix Jul 26 '21 at 03:46
  • 1
    @Matrix You could probably calculate a straight line between the last and current point and fill that line with points. – Jonas Jul 27 '21 at 14:57
8

if anyone still looking for answer then,

function track(e) {
  console.log("X - ", e.pageX, " Y - ", e.pageY);
}
addEventListener("mousemove", track, false);

paste this code in console to see immediate action

Pawan Deore
  • 162
  • 3
  • 10
5

If just want to track the mouse movement visually:

<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<style type="text/css">
* { margin: 0; padding: 0; }
html, body { width: 100%; height: 100%; overflow: hidden; }
</style>
<body>
<canvas></canvas>

<script type="text/javascript">
var
canvas    = document.querySelector('canvas'),
ctx       = canvas.getContext('2d'),
beginPath = false;

canvas.width  = window.innerWidth;
canvas.height = window.innerHeight;

document.body.addEventListener('mousemove', function (event) {
 var x = event.clientX, y = event.clientY;

 if (beginPath) {
  ctx.lineTo(x, y);
  ctx.stroke();
 } else {
  ctx.beginPath();
  ctx.moveTo(x, y);
  beginPath = true;
 }
}, false);
</script>
</body>
</html>
luistar15
  • 163
  • 1
  • 9
4

document.addEventListener('mousemove', (event) => {
  document.getElementById("line").style.top = event.clientY - 10 + 'px';
  document.getElementById("lineY").style.left = event.clientX - 10 + 'px';
  document.getElementById("pos").style.top = (event.clientY - 60) + 'px';
  document.getElementById("pos").style.left = (event.clientX - 60) + 'px';
});
body {
  position: relative;
  height: auto;
  min-height: 100% !important;
  background-color: lightblue;
}

h1 {
  color: white;
  text-align: center;
}

p {
  font-family: verdana;
  font-size: 20px;
}

.abs {
  position: relative;
}

.lineY {
  display: flex;
  position: relative;
  left: 0px;
  background-color: black;
  width: 2px;
  height: 100vh;
  min-height: 100%
}

.line {
  display: flex;
  position: relative;
  background-color: black;
  min-height: 2px;
  width: 100%;
}

.circle {
  display: flex;
  position: absolute;
  left: 0px;
  top: 0px;
}
<div class='line' id="line"></div>
<div class='lineY' id="lineY"></div>
<svg height="100" width="100" id="pos" class="circle">
  <circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="transparent" />
</svg>
Henry Ecker
  • 34,399
  • 18
  • 41
  • 57
baijugoradia
  • 140
  • 7
3

Irrespective of the browser, below lines worked for me to fetch correct mouse position.

event.clientX - event.currentTarget.getBoundingClientRect().left
event.clientY - event.currentTarget.getBoundingClientRect().top
Moritz Ringler
  • 9,772
  • 9
  • 21
  • 34
2

I don't have enough reputation to post a comment reply, but took TJ Crowder's excellent answer and fully defined the code on a 100ms timer. (He left some details to the imagination.)

Thanks OP for the question, and TJ for the answer! You're both a great help. Code is embedded below as a mirror of isbin.

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Example</title>
  <style>
    body {
      height: 3000px;
    }
    .dot {
      width: 2px;
      height: 2px;
      background-color: black;
      position: absolute;
    }
  </style>
</head>
<body>
<script>
(function() {
    "use strict";
    var mousePos;

    document.onmousemove = handleMouseMove;
    setInterval(getMousePosition, 100); // setInterval repeats every X ms

    function handleMouseMove(event) {
        var eventDoc, doc, body;

        event = event || window.event; // IE-ism

        // If pageX/Y aren't available and clientX/Y are,
        // calculate pageX/Y - logic taken from jQuery.
        // (This is to support old IE)
        if (event.pageX == null && event.clientX != null) {
            eventDoc = (event.target && event.target.ownerDocument) || document;
            doc = eventDoc.documentElement;
            body = eventDoc.body;

            event.pageX = event.clientX +
              (doc && doc.scrollLeft || body && body.scrollLeft || 0) -
              (doc && doc.clientLeft || body && body.clientLeft || 0);
            event.pageY = event.clientY +
              (doc && doc.scrollTop  || body && body.scrollTop  || 0) -
              (doc && doc.clientTop  || body && body.clientTop  || 0 );
        }

        mousePos = {
            x: event.pageX,
            y: event.pageY
        };
    }
    function getMousePosition() {
        var pos = mousePos;
  
        if (!pos) {
            // We haven't seen any movement yet, so don't add a duplicate dot 
        }
        else {
            // Use pos.x and pos.y
            // Add a dot to follow the cursor
            var dot;
            dot = document.createElement('div');
            dot.className = "dot";
            dot.style.left = pos.x + "px";
            dot.style.top = pos.y + "px";
            document.body.appendChild(dot);
        }
    }
})();
</script>
</body>
</html>
2

Here is a solution

document.onmousemove = showCoords;
function showCoords(event) {
var x = event.clientX;
var y = event.clientY;
var coords = "X coords: " + x + ", Y coords: " + y;
document.getElementById("box1").innerHTML = coords;
}
2
[...document.querySelectorAll("*")].forEach(h => h.addEventListener("mousemove", function(event) {
    console.table({
        "mouse x": event.clientX,
        "mouse y": event.clientY
    });
}));
sjaustirni
  • 3,056
  • 7
  • 32
  • 50
1

Here is the simplest way to track your mouse position

Html

<body id="mouse-position" ></body>

js

document.querySelector('#mouse-position').addEventListener('mousemove', (e) => {
        console.log("mouse move X: ", e.clientX);
        console.log("mouse move X: ", e.screenX);


    }, );

know more

MD SHAYON
  • 7,001
  • 45
  • 38
1

This is the shortest way to get the coordinates of mouse pointer. Just put your element where cursor is going to hover, inside $("")

 $("***enter you element here***").mousemove(function(event)
{
 console.clear()
  var x = event.originalEvent.screenX;
  var y = event.originalEvent.screenY;
  console.log("x : "+x)
  console.log("y : "+y)
})
KAVYA SHARMA
  • 39
  • 1
  • 5
0

Here’s a combination of the two requirements: track the mouse position, every 100 milliseconds:

var period = 100,
    tracking;

window.addEventListener("mousemove", function(e) {
    if (!tracking) {
        return;
    }

    console.log("mouse location:", e.clientX, e.clientY)
    schedule();
});

schedule();

function schedule() {
    tracking = false;

    setTimeout(function() {
        tracking = true;
    }, period);
}

This tracks & acts on the mouse position, but only every period milliseconds.

Bobby Jack
  • 15,689
  • 15
  • 65
  • 97
0

We recently had to find the current x,y position to enumerate elements over which the cursor is hovering independent of z-index. We ended up just attaching a mousemove event listener to document e.g.,

function findElements(e) {
  var els = document.elementsFromPoint(e.clientX, e.clientY);

  // do cool stuff with els
  console.log(els);

  return;
}

document.addEventListener("mousemove", findElements);
DotDotJames
  • 372
  • 4
  • 5
0

This should work, and it doesn't look nasty either.

class MousePosition {
  constructor(debug = false) {

    /*
      If you set debug to true, it will log the position.
    */
    
    this.d = debug
    this.x = 0;
    this.y = 0;
    this.mouseMoveHandler = this.handleMouseMove.bind(this);
    document.addEventListener('mousemove', this.mouseMoveHandler);
  }

  handleMouseMove(event) {
    this.x = event.clientX;
    this.y = event.clientY;
    if (this.d == true) {
      console.log(this.x, this.y)
    }
  }

  removeListener() {
    document.removeEventListener('mousemove', this.mouseMoveHandler);
  }
}