网页元素坐标表示及坐标计算方法

一、页面元素坐标种类

    根据DOM的鼠标事件(参见https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent),浏览器响应鼠标事件时,会上报四类坐标:

1、(pageX,pageY):相对于整个网页的坐标,因此坐标点可能比实际屏幕尺寸大。该坐标属于绝对坐标,不随着页面滚动而变化,当网页渲染完毕后,每个元素的page坐标就已固定。

2、(clientX, clientY):相对于当前视图区域的坐标,如果元素属于iframe,则是相对于iframe窗口坐标。

3、(offsetX,offsetY):鼠标位置相对于捕获事件的目标节点的坐标,如果点击位置没有元素,则为相对于body元素的坐标。

4、(screenX,screenY):相对于显示屏幕的坐标。

5、(layerX, layerY):非标准的特性,可能存在兼容性问题。表示鼠标点相对于该布局层顶端和左端的坐标,一般情况下与pageX、pageY相同,属于该层的绝对坐标。

但上述坐标中,哪些坐标是Web内核计算输出的,哪些坐标是传给Web内核的呢?其实,浏览器内核的输入坐标只有两个:屏幕坐标(screenX、screenY)和视图坐标(鼠标点相较于浏览器视图窗口的坐标)。其余4类坐标均是计算而来。

 

二、Chromium/Chrome浏览器鼠标事件捕获

Chromium浏览器在触发鼠标(如点击)事件时,主程序首先获得鼠标相对于视图区域(即去除浏览器应用顶部条、地址栏、工具栏、底部栏)的坐标(视图坐标),并在传给WebKit内核(或Render进程)前计算出该坐标对应的屏幕坐标(即screenX和screenY),将此两类坐标封装成WebMouseEvent对象。流程参见RenderWidgetHostViewAura::OnMouseEvent(ui::MouseEvent* event)。上述page、client、offset、layer坐标均是在Chromium内核中通过输入的视图区域坐标计算生成。

因此,对于点击某元素而言,浏览器视图窗口坐标是最重要的。

 

三、元素视图窗口坐标计算方法

元素相对于当前DOM视图窗口的坐标可通过getBoundingClientRect()计算而得。但当要计算该元素相对于浏览器视图区域的坐标,尤其针对该元素嵌入在某iframe中的情况,则需要利用getBoundingClientRect()迭代计算而成。代码如下:

  1.  
    var targetObj=document.getElementById('test'); //假设网页中存在一个id为test的元素
  2.  
     
  3.  
    function calcViewportLocation(obj, winObj) {
  4.  
    var currentWindow = winObj;
  5.  
    var rect = obj.getBoundingClientRect(); //获取该元素在当前窗口视图区域的位置
  6.  
    var top = rect.top;
  7.  
    var left = rect.left;
  8.  
    var width = rect.width;
  9.  
    var height = rect.height;
  10.  
     
  11.  
    //若该元素在某iframe中,则计算该frame相较于父窗口的位置,并向上迭代直到主frame。元素的位置坐标需要累加iframe的偏移。
  12.  
    while (currentWindow.frameElement != null) {
  13.  
    var obj1 = currentWindow.frameElement;
  14.  
    currentWindow = currentWindow.parent;
  15.  
    rect = obj1.getBoundingClientRect();
  16.  
    if (rect.top > 0) { top += rect.top; }
  17.  
    if (rect.left > 0) { left += rect.left; }
  18.  
    }
  19.  
    var final_x = Math.round(left);
  20.  
    var final_y = Math.round(top);
  21.  
    return {y:final_y, x:final_x, w:width, h:height};
  22.  
    }
  23.  
     
  24.  
    //将该元素对象及所在window作为参数传入。
  25.  
    var result = calcViewportLocation(targetObj, window);

将上述脚本注入到目标元素所在DOM上下文中即可。(注意,若所在元素在iframe中,则Chrome类浏览器需要设定--disable-web-security --allow-file-access-from-files启动参数,否则会因跨域问题无法计算iframe尺寸。)

诸如下图例子(假设要计算子frame中iframeButton2元素的浏览器视图坐标):

 

蓝色横线表示iframeButton2元素坐上角相对于其所在iframe视图窗口的坐标,数值为X(92,51),只需要targetObj.getBoundingClientRect()即可计算得到。而相对于浏览器视图窗口的坐标则为(380,59),是X加上元素所在iframe的视图窗口位置所得。

 

转:https://blog.csdn.net/weixin_42080566/article/details/80105259

posted @ 2020-11-15 15:42  左正  阅读(1905)  评论(0编辑  收藏  举报