25

In chrome canary, layerX and layerY are deprecated, but what should we use instead ?

I've find offsetX but it doesn't work with Firefox. So to get layerX without warning on webkit, I've done that :

var x = evt.offsetX || evt.layerX,
    y = evt.offsetY || evt.layerY;

But this seem quite complex ! Is that really what we should do to get layerX working in all browsers ?

Nicolas BADIA
  • 5,612
  • 7
  • 43
  • 46

5 Answers5

21

Here is a function to calculate layerX and layerY from a click event:

function getOffset(evt) {
  var el = evt.target,
      x = 0,
      y = 0;

  while (el && !isNaN(el.offsetLeft) && !isNaN(el.offsetTop)) {
    x += el.offsetLeft - el.scrollLeft;
    y += el.offsetTop - el.scrollTop;
    el = el.offsetParent;
  }

  x = evt.clientX - x;
  y = evt.clientY - y;

  return { x: x, y: y };
}

Thanks a lot to Stu Cox for pointing out the two functions used to make this one.

Nicolas BADIA
  • 5,612
  • 7
  • 43
  • 46
  • 2
    Sorry, but this doesn't seem to get always the same values that layerX and layerY ... Looks like we have to keep looking for THE solution... – Alejandro Rizzo Aug 27 '12 at 12:41
  • 1
    Just to complete the answer, take care with `var x = y = 0` because you're declaring `y` as global. – fmvilas Jan 30 '14 at 10:21
7

Are you sure layerX and layerY are deprecated?

In my experience they are still there, mostly because the related properties offsetX and offsetY are not implemented in other browsers:

There is a lot of discussion going on at webkit and mozilla though:

https://bugs.webkit.org/show_bug.cgi?id=21868 and https://bugzilla.mozilla.org/show_bug.cgi?id=674292 In a nutshell, they are both a bit inconclusive whether or not to remove it, so for now they did not remove it.

later IE versions provide an alias that maps to the x and y properties (I am not allowed to post any further links by stack overflow, because of a lack of 'reputation').

Sanne
  • 91
  • 1
  • 3
6

The only reasonably cross-browser ways to detect mouse position are clientX/clientY (relative to window), screenX/screenY (relative to entire screen) and pageX/pageY (relative to document, but not supported in IE8 and below).

Quirksmode suggests this for standardising to a relative-to-document value:

function doSomething(e) {
    var posx = 0;
    var posy = 0;
    if (!e) var e = window.event;
    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;
    }
    // posx and posy contain the mouse position relative to the document
    // Do something with this information
}

Then you could use this to work out its position relative to your element.

Horrible, I know, but the internet's a horrible place.

Magnus Lind Oxlund
  • 304
  • 1
  • 6
  • 19
Stu Cox
  • 4,486
  • 2
  • 25
  • 28
4

I know this is fairly old at this point but heres how I solved this issue for layerX.

   function getLayerX(event) {
     return event.clientX - event.target.getBoundingClientRect().x
   }

Im not sure this will work in all use cases, but this is what worked for me so I figured id share.

0

The provided solution fails to account for the root element scrollOffset. Here's my code for this task:

[layerX, layerY] = [...(function*() {  
    for (var el = ev.target; 
         el && !isNaN(el.offsetLeft) && !isNaN(el.offsetTop); 
         el = el.offsetParent) yield el; 
    yield document.documentElement; })()
  ]
  .map(el => [ -el.offsetLeft + el.scrollLeft, -el.offsetTop + el.scrollTop ])
  .reduce( 
    (acc, coords) => [ acc[0] + coords[0], acc[1] + coords[1] ], 
    [ ev.clientX, ev.clientY] );
Sérgio Carvalho
  • 1,135
  • 1
  • 8
  • 8