首頁  >  文章  >  web前端  >  JavaScript中計算網頁中某個元素的位置_javascript技巧

JavaScript中計算網頁中某個元素的位置_javascript技巧

WBOY
WBOY原創
2016-05-16 15:56:141012瀏覽

由於專案的需要,測試中需要對網頁元素進行截圖,以確保它看起來沒有問題。之前我寫過一篇文章介紹過一種方法,先使用WebDriver 進行全螢幕截圖,然後根據目標元素(DOM Element)所在的位置,再對截下來的圖片進行剪裁,保留我們需要的位置即可。

那段程式碼一直都運作得很好,直到我知道了一個東西:iframe。 iframe(普通的 frame 也是一樣的,不過 frame 現在不太常見,這裡只用 iframe 舉例)中的內容被視為一個獨立的網頁,連 Window 物件也是和它的父級網頁分開的。而WebDriver 中的WebElement.getLocation()方法只能回傳這個WebElement 和它所在的Window 的位置關係,它的實作沒什麼問題,但全螢幕截圖不僅包含了iframe 的內容,可能也包含了它的父級頁面的內容,剪裁的時候需要知道目標元素在截圖中的位置。那麼問題來了,挖土機技術哪家強?如何計算一個元素相對於截圖的位置?

這個問題還要分類討論,原因是:Chrome 和 Firefox 中截圖的行為是不一樣的。 Chrome 的截圖是目前可見(viewport)的網頁內容,比方說,當網頁的實際大小超過 Chrome 視窗大小時,根據捲軸的位置不同,視窗中顯示的內容不同,Chrome 的截圖就是顯示出來的內容。於是我們要計算目標元素相對於目前可見內容的位置。而 Firefox 用了一個方法,可以截到整個網頁的內容,無視於目前視窗大小。於是對於 Firefox 我們要計算元素的絕對位置(Absolute Position)。

取得一個元素的位置,需要用到一個方法:Element.getBoundingClientRect()。這個方法傳回這個元素相對於它所處的 Windows 在目前可見內容的位置,以 top、left、right、bottom 四個值來表示。我們只關心其中的 top 和 left,至於剪裁的尺寸,我們可以透過元素本身的長度和寬度來得到,不需要計算。要計算目標元素對於頂級 Window的位置,我們只需要依序加上它的父級 Window的 top 和 left 即可。程式碼如下:

function calcViewportLocation(element) {
 var currentWindow = window;
 var rect = element.getBoundingClientRect(); // 元素的位置
 var top = rect.top;
 var left = rect.left;
 while (currentWindow.frameElement != null) { // 处理父级 Window
  element = currentWindow.frameElement;
  currentWindow = currentWindow.parent;
  rect = element.getBoundingClientRect();
  if (rect.top > 0) { top += rect.top; }
  if (rect.left > 0) { left += rect.left; }
 }
 return [Math.round(top), Math.round(left)];
}

以上程式碼適用於 Chrome ,而在 Firefox 中,我們還需要計算元素的絕對位置。這裡需要用到 Window.pageXOffset。 pageXOffset,或 scrollX,表示目前 Window 的橫向捲軸滾動的位置,把這個值和上述的 left 相加,即可得到目標元素的橫向絕對位置。當然,iframe 也可以特別處理的:

function calcAbsolutLocation(element) {
 var top = 0;
 var left = 0;
 var currentWindow = window;
 while (element != null) {
  rect = element.getBoundingClientRect();
  var pageYOffset = currentWindow.pageYOffset;
  var pageXOffset = currentWindow.pageXOffset;
  if (typeof pageYOffset === 'undefined') { // IE8
   currentDocument = currentWindow.document;
   var bodyElement = (currentDocument.documentElement
     || currentDocument.body.parentNode || currentDocument.body);
   pageYOffset = bodyElement.scrollTop;
   pageXOffset = bodyElement.scrollLeft;
  }
  top += rect.top + pageYOffset;
  left += rect.left + pageXOffset;
  element = currentWindow.frameElement;
  currentWindow = currentWindow.parent;
  if (element != null) {
   style = window.getComputedStyle(element);
   top += parseInt(style.borderTopWidth, 10);
   left += parseInt(style.borderLeftWidth, 10);
  }
 }
 return [Math.round(top), Math.round(left)];
}


由於 IE8 不支援 pageXOffset 和 scrollX,於是在 IE8 中需要一些特殊處理,即程式碼中標註「IE8」的部分。將這兩段 Javascript 程式碼,取代先前文中的 WebElement.getLocation(),即可實作在 iframe 中對特定元素截圖。

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn