event.offsetX in Firefox

43,406

Solution 1

Try layerX, layerY

var x = (e.offsetX === undefined) ? e.layerX : e.offsetX;
var y = (e.offsetY === undefined) ? e.layerY : e.offsetY;

FIDDLE

Solution 2

From a JQuery bug tracker page - a nice polyfill is this:

var offX  = (e.offsetX || e.pageX - $(e.target).offset().left);

.. where e is the event returned from a jquery event. Obviously, only if you've got Jquery already on your project, otherwise will have to do the offset() stuff manually.

Solution 3

Unfortunately no solution worked for me.

I found a good implementation here:

var target  = e.target || e.srcElement,
              rect    = target.getBoundingClientRect(),
              offsetX = e.clientX - rect.left,
              offsetY  = e.clientY - rect.top;

e.offsetX   = offsetX;
e.offsetY   = offsetY;

Solution 4

Unfortunately offsetX and layerX are not exactly the same as offsetX is the offset within the current element but layerX is the offset from the page. Below is a fix I am currently using for this:

function fixEvent(e) {
    if (! e.hasOwnProperty('offsetX')) {
        var curleft = curtop = 0;
        if (e.offsetParent) {
           var obj=e;
           do {
              curleft += obj.offsetLeft;
              curtop += obj.offsetTop;
           } while (obj = obj.offsetParent);
        }
        e.offsetX=e.layerX-curleft;
        e.offsetY=e.layerY-curtop;
    }
    return e;
}

Solution 5

There's a bug in Musa's solution: think what happens if e.offsetX === 0 and e.layerX === undefined...

var x = e.offsetX || e.layerX; // x is now undefined!

A more robust version is as follows:

var x = e.hasOwnProperty('offsetX') ? e.offsetX : e.layerX;
var y = e.hasOwnProperty('offsetY') ? e.offsetY : e.layerY;

Or, because we can assume that if offsetX is defined, offsetY will be too:

var hasOffset = e.hasOwnProperty('offsetX'),
    x         = hasOffset ? e.offsetX : e.layerX,
    y         = hasOffset ? e.offsetY : e.layerY;
Share:
43,406

Related videos on Youtube

lviggiani
Author by

lviggiani

I've a 20y experience in the eLearning and Computer Based Training, with a special focus on aviation (pilots and maintenance staff) training. I've good design and programming skill, including the following languges and toolkits, tools and Operarting Systems: NodeJS Java (special focus on server side and client side cross-platform development and deployment) JavaScript / HTML5 / CSS3 (special focus on cross browser and cross devices development and optimizations for Mobile) C# C++ / Vala C / Objective-C PHP SQL SWT, GTK+, Cocoa ANT Flash and ActionScript 3 and 2 Inkscape, Gimp, Photoshop etc 3D Studio Max and Blender (basic) Linux, Windows, OS X, Android an iOS SVN, GIT Bugzilla, Mantis, JIRA I've a long experience in team working and management, software management, bug tracking and quality assurance, customer relationship management and problem solving. I'm a big fan of the OpenSource world and GNU/Linux. Most of my knowledge and skills come from passion, self-training and direct experience. SOreadytohelp

Updated on November 29, 2020

Comments

  • lviggiani
    lviggiani over 3 years
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    <script language="javascript">
    function main(){
        var canvas = document.getElementById("canvas");
        canvas.addEventListener("mousemove", function(e){
            if (!e) e = window.event;
            var ctx = canvas.getContext("2d");
    
            var x = e.offsetX;
            var y = e.offsetY;
    
            ctx.fillRect(x, y, 1, 1);
        });
    }
    </script>
    </head>
    <body onload="main();">
    <div style="width: 800px; height: 600px; -webkit-transform: scale(0.75,0.75); -moz-transform: scale(0.75,0.75)">
        <canvas id="canvas" width="400px" height="400px" style="background-color: #cccccc;"></canvas>
    </div>
    </body>
    </html>
    

    Please consider the above quick and dirty example. Please notice that my canvas is contained by a div having a scale transform applied. The above code works perfectly on any webkit based browser. While moving the mouse it draws points on the canvas. Unfortunately it doesn't in Firefox as its event model does not support the offsetX / Y properties. How can I transform mouse coordinates from (perhaps) event.clientX (which is supported in firefox too) into canvas relative coordinates taking into account canvas position, transform etc? Thanks, Luca.

    • Pikamander2
      Pikamander2 almost 9 years
      Thankfully, Firefox 40 supports offsetX!
  • jhoff
    jhoff almost 12 years
    This doesn't work for me, because the firefox event has 'offsetX/Y' but both are undefined. For what it's worth.
  • Mark Whitaker
    Mark Whitaker almost 12 years
    Bad Mozilla! In that case adjust appropriately - thanks for flagging it up.
  • Ivan Kochurkin
    Ivan Kochurkin over 11 years
    Unfortunately, Firefox layerX and layerY properties are differs from ones in other browsers. There are relative top-left corner of page, but not elemenet.
  • Denis
    Denis about 11 years
    wow. from all answers, only this one working for me. i've tried this with absolutely positioned element, thank you man so much! best answer in this topic
  • Denis
    Denis about 11 years
    var eoffsetX = (e.offsetX || e.clientX - $(e.target).offset().left + window.pageXOffset ), eoffsetY = (e.offsetY || e.clientY - $(e.target).offset().top + window.pageYOffset ); this fix will help if you have scrolled the page
  • Ivan Castellanos
    Ivan Castellanos almost 11 years
    false, they are relative to the closest offsetParent including the element itself, just add "position:relative" to the element you want to use for coordenates.
  • GameAlchemist
    GameAlchemist over 10 years
    var x = e.offsetX || e.layerX || 0 ; is a simpler solution.
  • Drew Noakes
    Drew Noakes over 10 years
    +1 for a non-jQuery solution that maintains the same semantics as offsetX and offsetY.
  • Alex
    Alex over 10 years
    Under Firefox 26.0 there is no field named 'offsetParent' in the event (e) thus initial e.offsetParent does not work ('if' is simply ignored). A solution might be to have e.target.offsetParent
  • Langdon
    Langdon over 10 years
    @Alex e.target.offsetParent doesn't work either. Did you come up with a fix for this?
  • Palani
    Palani over 10 years
    Didn't work for me, but this worked stackoverflow.com/questions/12704686/…
  • Anil kumar
    Anil kumar about 10 years
    Thanks @Denis, your answer of adding y position really helped me in fixing my issue
  • Milanka
    Milanka almost 10 years
    Bug tracker page has changed since the answer. It says you should use e.pageX instead of e.clientX. It fixes the problem with scrolled page, too. Works in latest Chrome, FF, and IE.
  • cristiano2lopes
    cristiano2lopes over 9 years
    Didn't work on FF 32.0.3 . layerX and layerY are absent from event.
  • Mike 'Pomax' Kamermans
    Mike 'Pomax' Kamermans over 9 years
    @Musa can you ammend this answer to note that position:relative is necessary to force these properties to be relative to the element, rather than an ancestor?
  • Adrian Maire
    Adrian Maire over 9 years
    layerX and offsetX are not the same, if the target is an inline element, the offset give the position of the cursor in the element, but return a layerX relative to his non-inline parent container.
  • Adrian Maire
    Adrian Maire over 9 years
    layerX and offsetX are not the same, if the target is an inline element, the offset give the position of the cursor in the element, but return a layerX relative to his non-inline parent container.
  • snapfractalpop
    snapfractalpop over 9 years
    @cristiano2lopes if you are using jQuery, you may you have to use event.originalEvent.layerX.
  • igelineau
    igelineau almost 9 years
    + 1 - this is the only solution that worked for me, with the only change being using e.target.offsetParent instead of e.offsetParent. I'm using RaphaelJS to draw objects in a map. With this code, I always get the right mouse coordinates even if e.target is sometimes the circle being drawn and sometimes the map canvas.
  • Marco Faustinelli
    Marco Faustinelli over 8 years
    @AdrianMaire - would you care to specify which ones?
  • danp
    danp over 8 years
    Seems that FF, since version 39, now supports this property. Good news!
  • schellmax
    schellmax over 5 years
    should be noted that this is meant to be used inside a jquery event handler, as jquery wraps the original event in a custom object, with access to the former via ´originalEvent´
  • Andrew
    Andrew almost 4 years
    developer.mozilla.org/en-US/docs/Web/API/UIEvent/layerX "This feature is non-standard and is not on a standards track. Do not use it on production sites facing the Web: it will not work for every user. There may also be large incompatibilities between implementations and the behavior may change in the future."
  • Andrew
    Andrew almost 4 years
    For those who are still having problems with offsetX and offsetY, you may want to look into this: developer.mozilla.org/en-US/docs/Web/API/Element/…