[英]getting mouse position relative to content area of an element
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: 并且我将获得相对于元素
element
的鼠标位置:
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. 因为
offsetLeft
和offsetTop
是元素的“外部”左上角与其偏移父级的“内部”左上角之间的差异,所以总和位置将跳过层次结构中的所有边框和填充。
Here's a comparison that should (hopefully) clarify what I mean. 这是一个比较,应该(希望)澄清我的意思。
Here's a live example that uses an element_position()
function that is aware of padding and borders. 这是一个实例,它使用了一个知道填充和边框的
element_position()
函数。 I've added some extra padding and margins to your original example. 我在原始示例中添加了一些额外的填充和边距。
http://jsfiddle.net/Skz8g/4/ 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. 在此示例和稍后的示例中,
canvas x
和canvas y
读数指示相对于画布内容的光标位置。
Here's the code for element_position()
: 这是
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. 代码应该在IE9,FF和Chrome中正常工作,虽然我注意到它在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. 我最初倾向于使用类似
e.offsetX/Y
属性的东西,因为它们更接近你想要的东西,并且不涉及循环嵌套元素。 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/ http://jsfiddle.net/xUZAa/6/
It should work across all modern browsers - Opera, FF, Chrome, IE9. 它应该适用于所有现代浏览器 - 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. 我个人更喜欢它,但认为虽然你的原始问题只是“相对于元素的内容区域获取鼠标位置”,但你真的在询问如何使
element_position()
函数正常工作。
using jQuery: 使用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;
};
live example: http://jsfiddle.net/vGKM3/ 实例: http : //jsfiddle.net/vGKM3/
The root of this is simple: compute the element's position relative to the document. 这个的根本很简单:计算元素相对于文档的位置。 I then drop the top & left padding & border (margin is included with basic positioning calculations).
然后我放下顶部和左边的填充和边框(边距包含在基本定位计算中)。 The internal jQuery code for doing this is based on
getComputedStyle
and element.currentStyle
. 用于执行此操作的内部jQuery代码基于
getComputedStyle
和element.currentStyle
。 Unfortunately I don't think there is another way... 不幸的是我不认为还有另一种方式......
The core of jQuery's .offset()
function, which gets an element's position relative to document: 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
}
Theoretically, another way to do this would be, using the above positioning code: 从理论上讲,另一种方法是使用上面的定位代码:
position: relative
(or absolute) set position: relative
(或绝对)设置 position: absolute; top:0px; left:0px;
position: absolute; top:0px; left:0px;
附加一个新元素position: absolute; top:0px; left:0px;
position: absolute; top:0px; left:0px;
In your element_position(e)
function, iterate through the hierarchy using parentNode
, get the padding, offsets and border using getComputedStyle(e, null).getPropertyValue(each_css)
, and sum them to the value of your x
and y
values before return. 在
element_position(e)
函数中,使用parentNode
迭代层次结构,使用getComputedStyle(e, null).getPropertyValue(each_css)
获取填充,偏移和边框,并在返回之前将它们与x
和y
值的值相加。
There's a post proposing a cross-browser reading of styles here: 有一篇帖子提出了跨浏览器阅读样式:
http://bytes.com/topic/javascript/answers/796275-get-div-padding http://bytes.com/topic/javascript/answers/796275-get-div-padding
I am not sure if this is the best way, or most resource efficient... 我不确定这是最好的方式,还是资源效率最高......
But I would suggest getting X/Y for the canvas tag, width of the border, and padding and using them all together as the offset. 但我建议为画布标签获取X / Y,边框宽度和填充,并将它们一起用作偏移量。
Edit: 编辑:
Use offsetLeft and offsetTop 使用offsetLeft和offsetTop
Reference: How to Use the Canvas and Draw Elements in HTML5 参考: 如何在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.