2011-03-28 63 views
5

我试图获取页面上元素的坐标。我一直在使用的标准的方式来获得它:使用内联偏移量获取元素左侧/顶部的实际偏移量

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描述的事实:

The element starts in the middle of the text

后一些用jQuery试图事实证明,他们的.offset() - 方法返回正确的偏移,我已经通过源看了,但不完全是如何发现他们这样做。所以我的问题是:我如何得到确切的位置?我不能在这个项目中使用jQuery,并且the thread described earlier中的方法很麻烦,添加一个元素并且测试工作太多(性能角度),并且使用Element.getBoundingClientRect也不可用。

如果你喜欢尝试出来,你可以去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渲染引擎,澄清。

回答

2

我最终用WebKit的window.webkitConvertPointFromNodeToPage去了,但我一直在碰到一个错误,它会返回一个完全错误的位置。进一步调查发现,如果有问题的节点是display:inline,那么它将返回层次结构中最后一个块元素的位置。

搜索此图像的分辨率没有任何反应(我发现的所有内容都是关于webkitConvertPointFromNodeToPage实际上做了什么以及WebKit的源代码的非常基本的信息)。

通过猜测我发现它返回了正确的位置,如果元素有display: inline-block,所以如果元素是内联的,那么我将它改为内联块,然后计算位置。

如果有人对此问题有更好的解决方案,我很乐意听取您的意见!

编辑:

原来改变显示风格,以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) 
} 

我取内联孩子的偏移量Top/Left并从其父母中减去它。我真的不确定它是如何在有显示功能的父母身上发挥作用的:内联,但在90%的时间内工作。

但是,如果任何人有一个更好的主意,我仍然开放的建议。

1

很可能here你会发现在the source code of jQuery.offset中使用的想法的描述。

如果你看看here你可以看到offsetLeftoffsetTop在旧的IE版本中不太正确。

我明白理解这个或其他东西可以如何实现是很有趣的。你如何看待jQuery.offset函数的源代码并不那么容易。如果你希望你的代码工作正确并且独立于浏览器,那么你最好只使用jQuery.offset而不是写他自己的实现。

1

检查webkitConvertPointFromNodeToPage源代码揭示它使用元素渲染器对象进行计算,如果不存在这样的渲染器,则它使用具有渲染器的neareset祖先。但是,当使用祖先渲染器时,它不会调整偏移量以考虑目标与祖先起源之间的原始差异。这意味着当相对于包含渲染器给出点时,该函数可以正确工作。如果你计算坐标的元素没有渲染器,你需要手动调整偏移到执行最近的祖先有它(使用offsetLeft /顶)。确切地知道哪些元素具有渲染器将需要更多的研究,但一般没有内容,但会影响其它节点,如SPAN的显示任何元素,不需要渲染。

1

我有同样的问题,当使用$.offset().left使用jQuery,试图得到一个字的段落内的位置。

$(document).ready()函数中使用$.offset().left产生了不正确的结果。

$(window).load()功能使用$.offset().left解决我的问题WebKit中。

在可能会影响布局的浮动图像元素或字体的情况下,这尤其相关。