Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

When the mouse is moved over an element, I want to get the mouse coordinates of the cursor relative to the top-left of the element's content area (this is the area excluding padding, border and outline). Sounds simple, right? What I have so far is a very popular function:

function element_position(e) {
    var x = 0, y = 0;
    do {
        x += e.offsetLeft;
        y += e.offsetTop;
    } while (e = e.offsetParent);
    return { x: x, y: y };
}

And I'd get the mouse position relative to an element element with:

p = element_position(element);
x = mouseEvent.pageX - p.x;
y = mouseEvent.pageY - p.y;

That isn't quite correct. Because the offsetLeft and offsetTop are the differences between the 'outer' top left of an element and the 'inner' top left of its offset parent, the sum position will skip over all borders and paddings in the hierarchy.

Here's a comparison that should (hopefully) clarify what I mean.

  • If I get the sum of the distances in position between the 'outer' top left of the elements and the 'inner' top left of their offset parents (outers minus inners; what I am doing right now), I get the element's content area's position, minus all the borders and paddings in the offset hierarchy.
  • If I get the sum of the distances in position between the 'outer' top left of the elements and the 'outer' top left of their offset parents (outers minus outers), I get the element's content area's position, minus the border and padding of the desired element (close, but not quite there).
  • If I get the sum of the distances in position between the 'inner' top left of the elements and the 'inner' top left of their offset parents (inners minus inners), I get the element's content area's position. This is what I want.
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
312 views
Welcome To Ask or Share your Answers For Others

1 Answer

Here's a live example that uses an element_position() function that is aware of padding and borders. I've added some extra padding and margins to your original example.

http://jsfiddle.net/Skz8g/4/

To use it, move the cursor over the brown area. The resulting white area is the actual canvas content. The brown is padding, the red is a border, and so on. In both this example and the one later on, the canvas x and canvas y readouts indicate the cursor position relative to canvas content.

Here's the code for element_position():

function getNumericStyleProperty(style, prop){
    return parseInt(style.getPropertyValue(prop),10) ;
}

function element_position(e) {
    var x = 0, y = 0;
    var inner = true ;
    do {
        x += e.offsetLeft;
        y += e.offsetTop;
        var style = getComputedStyle(e,null) ;
        var borderTop = getNumericStyleProperty(style,"border-top-width") ;
        var borderLeft = getNumericStyleProperty(style,"border-left-width") ;
        y += borderTop ;
        x += borderLeft ;
        if (inner){
          var paddingTop = getNumericStyleProperty(style,"padding-top") ;
          var paddingLeft = getNumericStyleProperty(style,"padding-left") ;
          y += paddingTop ;
          x += paddingLeft ;
        }
        inner = false ;
    } while (e = e.offsetParent);
    return { x: x, y: y };
}

The code should work properly in IE9, FF and Chrome, although I notice it is not quite right in Opera.

My original inclination was to use something like the e.offsetX/Y properties because they were closer to what you want, and do not involve looping over nested elements. However, their behaviour varies wildly across browsers, so a bit of cross-browser finagling is necessary. The live example is here:

http://jsfiddle.net/xUZAa/6/

It should work across all modern browsers - Opera, FF, Chrome, IE9. I personally prefer it, but thought that although your original question was just about "getting mouse position relative to content area of an element", you were really asking about how to make the element_position() function work correctly.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...