首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > Web前端 >

获得页面绝对位置有关问题探索

2012-11-23 
获得页面绝对位置问题探索?? 我们常常需要获得某个元素在页面的绝对位置,比如:经常需要弹出一个绝对定位的

获得页面绝对位置问题探索

?? 我们常常需要获得某个元素在页面的绝对位置,比如:经常需要弹出一个绝对定位的 div 在特定位置,有时是在一个元素的周围,有时是在鼠标单击的地方,如果我们方便的获得了 想要的页面绝对位置,那么指定 top left 属性即可,很方便,偏偏在这方面 IE 与标准却达不成一致,需要总结一下,Extjs 就是现成的桥接工具,帮我们屏蔽了各个浏览器的差异。


主要是 两个地方:


Ext.Element.getXY()


该方法获得页面中某个元素边框开始(不包括边框)的左,上,右和下分别相对浏览器视窗(即不包括滚屏长度)的位置,和浏览器模式无关。

?

测试代码:

?

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml">    <head>        <title>窗口测试</title>        <style type="text/css">        html,body{            margin:0;            border:0;            padding:0;        }        </style>    </head><body>    <div id="q"        style="border:1px solid red;padding:10px;margin:100px;width:600px;height:600px;position:relative;"        >        z        <div id="demo"        style="border:1px solid red;padding:10px;margin:100px;width:10px;height:10px;"        >        </div>        </div>        <script type="text/javascript">            alert(document.getElementById('demo').getBoundingClientRect().top - document.getElementById('q').getBoundingClientRect().top);        </script></body></html>
?

获得一个页面元素的绝对页面位置。这个方法主要利用了 getBoundingClientRect (注意:IE 默认body有边框,而 firefox,chrome 则没有)以及目前尚没有明确标准的offsetTop 以及 offsetParent,offsetTop 是指当前元素和他的包含块元素之间的高度差(详见:盒模型)。这点 ie ff 表现得基本一致,差别很小见下。但是对于相对元素offsetParent 却有争议(详见:offsetParent 探讨)。

?

1.如果存在 getBoundingClientRect

?

??? Ext 的方法用了 约定俗称 的 :

?

if (el.getBoundingClientRect) {                b = el.getBoundingClientRect();                scroll = fly(document).getScroll();                return [b.left + scroll.left, b.top + scroll.top];}
?

?

2. 其它

?

?? offsetParent 就是当前元素的已定位的祖先元素(position属性不等于static),因此并不一定是父元素offsetTop 不包括当前元素的上边框ie,ff 都认为 body 没有 offsetParent。


??于是粗略的讲,只要沿着 offsetParent 向上,累加 offsetTop 即可,Extjs正是这样做的,只不过对各个浏览器的细节进行了更多考虑,特别是当该元素的祖先元素们含有滚动条(overflow 不为 visible)时,要减去如:

?

//x,y 为根据 offsetTop offsetParent 方法 算出的 ,然后while (p && p != bd) {    if (!Ext.isOpera || (p.tagName != 'TR' && !fly(p).isStyle("display", "inline"))) {        x -= p.scrollLeft;        y -= p.scrollTop;    }    p = p.parentNode;}
??

?

?

x 坐标? 同 y 坐标。

?

Ext.EventObject.getPageY()

?

这个表示 当前事件的发生绝对页面位置 , 只有 是鼠标事件时才有效,例如单击 , 鼠标经过等。


w3c 中 直接 规定 event.pageX 为 当前事件的发生绝对页面位置。


而ie 没有直接的获得方式,ie 专有的 event.clientX 为绝对可见位置,(忽略了向上滚动条),则我们只需要把滚动条条滚掉的页面高度加上即可。即页面向上滚动了多少?正是body.scrollTop 属性,意思也很明白


元素 :body

行为 :scroll

方向 :top

值 body.scrollTop


如果页面处于 w3c 标准模式:那么以上的 body 就要换做 document.documentElement 了,标准模式时这些属性都放在html节点上了。


下篇 简析? Ext.EventObject 的怎么阻止默认事件发生,以及传统的return false.


PS: KISSY 实现 与 iframe 内元素的考虑:

?

考虑 iframe ,对其内的元素先求解在 iframe 的坐标,再递归向上求解 iframe element 在其包含的窗体中的坐标。

?

/**     * support elment in iframe     * @param elem     * @param refDocument     */    function getOffset(elem, refDocument) {        var box, x = 0,            y = 0,            currentWindow = elem.ownerDocument.defaultView || elem.ownerDocument.parentWindow,            currentDoc = elem.ownerDocument,            currentDocElem = currentDoc.documentElement;        // 1. 对于 body 和 docElem, 直接返回 0, 绝大部分情况下,这都不会有问题        // 2. 根据 GBS 最新数据,A-Grade Browsers 都已支持 getBoundingClientRect 方法,不用再考虑传统的实现方式        if (elem[GET_BOUNDING_CLIENT_RECT]) {            if (elem !== currentDoc.body && currentDocElem !== elem) {                box = elem[GET_BOUNDING_CLIENT_RECT]();                // 注:jQuery 还考虑减去 docElem.clientLeft/clientTop                // 但测试发现,这样反而会导致当 html 和 body 有边距/边框样式时,获取的值不正确                // 此外,ie6 会忽略 html 的 margin 值,幸运地是没有谁会去设置 html 的 margin                x = box.left + _scrollLeft(currentWindow, currentDocElem, currentDoc);                y = box.top + _scrollTop(currentWindow, currentDocElem, currentDoc);            }            if (refDocument) {                var refWindow = refDocument.defaultView || refDocument.parentWindow;                if (currentWindow != refWindow && currentWindow.frameElement) {                    //note:when iframe is static ,still some mistake                    var iframePosition = DOM.offset(currentWindow.frameElement, refDocument);                    x += iframePosition.left;                    y += iframePosition.top;                }            }        }        return { left: x, top: y };    }
?

PS2 : 设置页面绝对位置的探讨

热点排行