当鼠标在元素上移动时,我想获得光标相对于元素内容区域左上角的鼠标坐标(这是除了填充,边框和轮廓之外的区域)。听起来很简单吧?到目前为止我所拥有的是一个非常受欢迎的功能:
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;
这不太正确。由于offsetLeft
和offsetTop
是元素的“外部”左上角与其偏移父级的“内部”左上角之间的差异,因此总和位置将跳过全部层次结构中的边框和填充。
这是一个比较,应该(希望)澄清我的意思。
答案 0 :(得分:10)
这是一个使用element_position()
函数的实时示例,该函数知道填充和边框。我在原始示例中添加了一些额外的填充和边距。
要使用它,请将光标移到棕色区域上。生成的白色区域是实际的画布内容。棕色是填充物,红色是边框,依此类推。在此示例和稍后的示例中,canvas x
和canvas 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
属性的东西,因为它们更接近你想要的东西,并且不涉及循环嵌套元素。但是,它们在浏览器中的行为差别很大,因此需要进行一些跨浏览器的处理。现场的例子在这里:
它应该适用于所有现代浏览器 - Opera,FF,Chrome,IE9。我个人更喜欢它,但认为虽然你的原始问题只是“相对于元素的内容区域获得鼠标位置”,但你真的在询问如何使element_position()
函数正常工作。
答案 1 :(得分:4)
使用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代码基于getComputedStyle
和element.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;
答案 2 :(得分:2)
在element_position(e)
函数中,使用parentNode
遍历层次结构,使用getComputedStyle(e, null).getPropertyValue(each_css)
获取填充,偏移和边框,并将它们与x
的值相加返回前的y
值。
这里有一篇帖子建议跨浏览器阅读样式:
http://bytes.com/topic/javascript/answers/796275-get-div-padding
答案 3 :(得分:1)
我不确定这是最好的方式,还是资源效率最高的......
但我建议为画布标签获取X / Y,边框宽度和填充,并将它们一起用作偏移量。
编辑:
使用offsetLeft和offsetTop
参考:How to Use the Canvas and Draw Elements in 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;