我正在尝试获取页面上元素的坐标。我一直在使用标准方法来获取它:
var el = element, pos = {x: 0, y: 0};
while ( el ) {
pos.x += el.offsetLeft;
pos.y += el.offsetTop;
el = el.offsetParent;
}
但是当有问题的元素有display: block
时,此方法失败,而其中一个offsetParents有display: inline;
。这是由于this thread:
在尝试使用jQuery之后,事实证明他们的.offset()
- 方法返回了正确的偏移量,并且我查看了源代码,但没有找到他们是如何做到的。所以我的问题是:我如何获得确切的位置?我不能在这个项目中使用jQuery,the thread described earlier中的方法很麻烦,添加元素和测试工作太多(性能视角),并且使用Element.getBoundingClientRect
也不可用。< / p>
如果您想尝试一下,可以转到Apple.com打开您选择的调试器并输入以下内容:
var el, el2;
el = el2 = document.querySelector('#worldwide span');
var pos = {x: 0, y: 0};
while ( el2 ) {
pos.x += el2.offsetLeft;
pos.y += el2.offsetTop;
el2 = el2.offsetParent;
}
alert("Calculated position: " + pos.x + "x" + pos.y + " window size: " + screen.width + "x" + screen.height);
使用这段代码我得到:Calculated position: 1354x988 window size: 1280x800
(即左边的偏移是屏幕的方式,显然不是这样)
这怎么可能?任何解决方法的想法?约稿?它不一定非常精确,但必须比以前更好。感谢。
编辑:这是为WebKit渲染引擎澄清的。
答案 0 :(得分:2)
我最终选择了WebKit的window.webkitConvertPointFromNodeToPage
,但是我一直遇到一个错误,它会返回一个完全错误的位置。进一步的调查显示,如果有问题的节点显示为:inline,那么它将返回层次结构中最后一个块元素的位置。
搜索这个图像的分辨率没有任何结果(我发现的只是关于webkitConvertPointFromNodeToPage实际做了什么和WebKit的源代码的非常基本的信息)。
猜测我发现如果元素有display: inline-block
,它返回了正确的位置,所以如果元素是内联的,那么我将它改为内联块,然后计算位置。
如果有人对此问题有更好的解决方案,我很乐意听取您的意见!
修改强>
原来改变显示样式到内联块并不总是一个好主意,所以我没有这样做,而是使用这种方法:
var offset = {x: 0, y: 0};
if ( getStyle(el, 'display') == 'inline' ) {
offset.x = el.offsetLeft - el.parentNode.offsetLeft;
offset.y = el.offsetTop - el.parentNode.offsetTop;
}
var point = window.webkitConvertPointFromNodeToPage(el, new WebKitPoint(0, 0));
return {
x: Math.round(point.x + offset.x),
y: Math.round(point.y + offset.y)
}
我正在使用内联子项的offsetTop / Left并从它的父项中减去它。我不确定它如何适用于有显示内容的父母:内联,但它在90%的时间都有效。
但如果有人有更好的想法,我仍然愿意接受建议。
答案 1 :(得分:1)
可能here您会找到the source code of jQuery.offset中使用的提示的说明。
如果你看here,你可以看到offsetLeft
和offsetTop
在旧的IE版本中工作不正确。
我理解理解如何实现这些或其他事情很有意思。如何看待jQuery.offset
函数的源代码并不那么容易。如果您希望代码正常工作并且与浏览器无关,那么最好使用jQuery.offset
而不是编写自己的实现。
答案 2 :(得分:1)
对webkitConvertPointFromNodeToPage源代码的检查显示它使用元素渲染器对象计算,如果不存在这样的渲染器,则它使用具有渲染器的neareset祖先。但是,当使用祖先渲染器时,它不会调整偏移量来解释目标与其祖先原点之间的原点差异。这意味着当相对于包含渲染器给出该点时,该函数可以正常工作。如果您计算坐标的元素没有渲染器,则需要手动将偏移调整到最近的祖先(使用offsetLeft / Top)。要准确了解哪些元素具有渲染器需要更多研究,但通常任何没有内容但影响其他节点显示的元素(如SPAN)都不需要渲染器。
答案 3 :(得分:1)
在jQuery中使用$.offset().left
时遇到了同样的问题,试图获取段落中单词的位置。
在$.offset().left
函数中使用$(document).ready()
会产生错误的结果。
在$.offset().left
函数中使用$(window).load()
解决了我在WebKit中的问题。
在可能存在影响布局的浮动图像元素或字体的情况下,这尤其重要。