Home > Article > Web Front-end > Calculate the position of an element in a web page in JavaScript_javascript tips
Due to the needs of the project, screenshots of web page elements are required during testing to ensure that it looks normal. BeforeI wrote an article introducing a method, first use WebDriver to take a full-screen screenshot, and then crop the screenshot according to the location of the target element (DOM Element), retaining what we need location.
That code was working fine until I figured out something: iframe. The content in an iframe (ordinary frame is the same, but frame is less common now, only iframe is used as an example here) is regarded as an independent web page, and even the Window object is separated from its parent web page. The WebElement.getLocation() method in WebDriver can only return the positional relationship between this WebElement and the Window it is located in. There is no problem with its implementation, but the full-screen screenshot not only contains the content of the iframe, but may also include the content of its parent page. Content, you need to know the position of the target element in the screenshot when cropping. So the question is, which company has the best excavator technology? How to calculate the position of an element relative to the screenshot?
This issue needs to be discussed in a separate category. The reason is: the behavior of screenshots in Chrome and Firefox is different. Chrome's screenshot is the currently visible (viewport) web page content. For example, when the actual size of the web page exceeds the Chrome window size, the content displayed in the window is different depending on the position of the scroll bar. Chrome's screenshot is the displayed content. So we need to calculate the position of the target element relative to the currently visible content. Firefox uses a method that can capture the content of the entire web page, regardless of the current window size. So for Firefox we need to calculate the absolute position of the element (Absolute Position).
To obtain the position of an element, you need to use a method: Element.getBoundingClientRect(). This method returns the position of this element relative to the currently visible content of the Windows it is located in, represented by four values: top, left, right, and bottom. We only care about top and left. As for the clipping size, we can get it from the length and width of the element itself, without calculation. To calculate the position of the target element relative to the top-level Window, we only need to add the top and left of its parent Window in sequence. The code is as follows:
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)]; }
The above code works for Chrome, but in Firefox, we also need to calculate the absolute position of the element. Window.pageXOffset is needed here. pageXOffset, or scrollX, represents the scrolling position of the current Window's horizontal scroll bar. Add this value to the above left to get the horizontal absolute position of the target element. Of course, iframe can also be treated specially:
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)]; }
Since IE8 does not support pageXOffset and scrollX, some special processing is required in IE8, that is, the part marked "IE8" in the code. By replacing these two pieces of Javascript code with WebElement.getLocation() in the previous article, you can take a screenshot of a specific element in an iframe.