繁体   English   中英

获取相对于元素的内容区域的鼠标位置

[英]getting mouse position relative to content area of an element

当鼠标在元素上移动时,我想获得光标相对于元素内容区域左上角的鼠标坐标(这是不包括填充,边框和轮廓的区域)。 听起来很简单吧? 到目前为止我所拥有的是一个非常受欢迎的功能:

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 };
}

并且我将获得相对于元素element的鼠标位置:

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

这不太正确。 因为offsetLeftoffsetTop是元素的“外部”左上角与其偏移父级的“内部”左上角之间的差异,所以总和位置将跳过层次结构中的所有边框和填充。

这是一个比较,应该(希望)澄清我的意思。

  • 如果我得到元素的“外部”左上角和偏移父母的“内部”左上角之间的距离总和( outers减去内部 ;我现在正在做什么),我得到元素的内容区域position,减去偏移层次结构中的所有边框和填充。
  • 如果我得到元素的“外部”左上角和偏移父母的“外部”左上角之间的距离总和( outers减去outers ),我得到元素的内容区域的位置,减去边框和填充期望的元素(关闭,但不完全)。
  • 如果我得到元素的“内部”左上角和偏移父母的内部“内部”( 内部减去内部 )之间的距离总和,我得到元素的内容区域的位置。 这就是我要的。

这是一个实例,它使用了一个知道填充和边框的element_position()函数。 我在原始示例中添加了一些额外的填充和边距。

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

要使用它,请将光标移到棕色区域上。 生成的白色区域是实际的画布内容。 棕色是填充物,红色是边框,依此类推。 在此示例和稍后的示例中, canvas xcanvas y读数指示相对于画布内容的光标位置。

这是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 };
}

代码应该在IE9,FF和Chrome中正常工作,虽然我注意到它在Opera中并不完全正确。

我最初倾向于使用类似e.offsetX/Y属性的东西,因为它们更接近你想要的东西,并且不涉及循环嵌套元素。 但是,它们在浏览器中的行为差别很大,因此需要进行一些跨浏览器的处理。 现场示例如下:

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

它应该适用于所有现代浏览器 - Opera,FF,Chrome,IE9。 我个人更喜欢它,但认为虽然你的原始问题只是“相对于元素的内容区域获取鼠标位置”,但你真的在询问如何使element_position()函数正常工作。

使用jQuery:

function posRelativeToElement(elem, ev){
    var $elem = $(elem),
         ePos = $elem.offset(),
     mousePos = {x: ev.pageX, y: ev.pageY};

    mousePos.x -= ePos.left + parseInt($elem.css('paddingLeft')) + parseInt($elem.css('borderLeftWidth'));
    mousePos.y -= ePos.top + parseInt($elem.css('paddingTop')) + parseInt($elem.css('borderTopWidth'));

    return mousePos;
};

实例: http//jsfiddle.net/vGKM3/

这个的根本很简单:计算元素相对于文档的位置。 然后我放下顶部和左边的填充和边框(边距包含在基本定位计算中)。 用于执行此操作的内部jQuery代码基于getComputedStyleelement.currentStyle 不幸的是我不认为还有另一种方式......

jQuery的.offset()函数的核心,它获取元素相对于文档的位置:

if ( "getBoundingClientRect" in document.documentElement ) {
    ...
    try {
        box = elem.getBoundingClientRect();
    } catch(e) {}

    var body = doc.body,
        win = getWindow(doc),
        clientTop  = docElem.clientTop  || body.clientTop  || 0,
        clientLeft = docElem.clientLeft || body.clientLeft || 0,
        scrollTop  = (win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop ),
        scrollLeft = (win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft),
        top  = box.top  + scrollTop  - clientTop,
        left = box.left + scrollLeft - clientLeft;

    return { top: top, left: left };
}else{
    // calculate recursively based on .parentNode and computed styles
}

从理论上讲,另一种方法是使用上面的定位代码:

  • 确保你的元素有position: relative (或绝对)设置
  • position: absolute; top:0px; left:0px;附加一个新元素position: absolute; top:0px; left:0px; position: absolute; top:0px; left:0px;
  • 获取元素相对于文档的位置。 它将与父级的内容位置相同
  • 删除新元素

element_position(e)函数中,使用parentNode迭代层次结构,使用getComputedStyle(e, null).getPropertyValue(each_css)获取填充,偏移和边框,并在返回之前将它们与xy值的值相加。

有一篇帖子提出了跨浏览器阅读样式:

http://bytes.com/topic/javascript/answers/796275-get-div-padding

我不确定这是最好的方式,还是资源效率最高......

但我建议为画布标签获取X / Y,边框宽度和填充,并将它们一起用作偏移量。

编辑:

使用offsetLeft和offsetTop

参考: 如何在HTML5中使用画布和绘制元素

var x;
var y;
if (e.pageX || e.pageY) { 
  x = e.pageX;
  y = e.pageY;
}
else { 
  x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; 
  y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop; 
} 
x -= gCanvasElement.offsetLeft;
y -= gCanvasElement.offsetTop;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM