一、頁面元素坐標種類
根據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