网页元素坐标表示及坐标计算方法
一、页面元素坐标种类
根据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()迭代计算而成。代码如下:
-
var targetObj=document.getElementById('test'); //假设网页中存在一个id为test的元素
-
-
function calcViewportLocation(obj, winObj) {
-
var currentWindow = winObj;
-
var rect = obj.getBoundingClientRect(); //获取该元素在当前窗口视图区域的位置
-
var top = rect.top;
-
var left = rect.left;
-
var width = rect.width;
-
var height = rect.height;
-
-
//若该元素在某iframe中,则计算该frame相较于父窗口的位置,并向上迭代直到主frame。元素的位置坐标需要累加iframe的偏移。
-
while (currentWindow.frameElement != null) {
-
var obj1 = currentWindow.frameElement;
-
currentWindow = currentWindow.parent;
-
rect = obj1.getBoundingClientRect();
-
if (rect.top > 0) { top += rect.top; }
-
if (rect.left > 0) { left += rect.left; }
-
}
-
var final_x = Math.round(left);
-
var final_y = Math.round(top);
-
return {y:final_y, x:final_x, w:width, h:height};
-
}
-
-
//将该元素对象及所在window作为参数传入。
-
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