当前位置: 首页 > 编程笔记 >

JavaScript中计算网页中某个元素的位置

慕容超
2023-03-14
本文向大家介绍JavaScript中计算网页中某个元素的位置,包括了JavaScript中计算网页中某个元素的位置的使用技巧和注意事项,需要的朋友参考一下

由于项目的需要,测试中需要对网页元素进行截图,以确保它看上去没有问题。之前我写过一篇文章介绍过一种方法,先使用 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 中对特定元素截图。

 类似资料:
  • 问题内容: 假设我有一个带有不同种类标记的大型HTML文件,类似于您现在正在查看的StackOverflow。 现在,假设您单击页面上的一个元素,那么该Javascript函数将如何计算出引用该特定元素的最基本的XPath? 我知道在XPath中有无数种方式来引用该元素,但是我正在寻找一种只看DOM树而不考虑ID,类等的东西。 例: 假设您点击“ 苹果” 。Javascript函数将返回以下内容:

  • 问题内容: 我有10 秒之一。如何用另一个值更新索引? 问题答案: 让是和新的,那么就这样做: 可以在此处的Java api参考中找到。

  • 问题内容: 如果我有一个数组,我想检查数组中有多少个。在JavaScript中不使用循环循环的最优雅的方法是什么? 问题答案: 很简单:

  • 嗨,所以经过一些搜索仍然没有找到答案,但我想要得到一个网页的单个元素到一个字符串变量。我知道如何在C语言中实现这一点,但我想知道如何在java语言中实现这一点 例如: 谢谢 我需要将该值从网页中转换成一个字符串变量

  • 我想要做出一个自动点击“激励”按钮,然后提取“当前效率”的数值 代入公式\( (100-“当前效率”)×344 \) 计算出结果之后输入到输入框里,再点击确定按钮,并向下循环,直到所有“当前效率”的值都为100。 最好能用浏览器内嵌编译器。 我尝试写了一个脚本,通过Tampermonkey在浏览器中运行。 但它不能运行,因为我编程能力有限,没能排查出问题。

  • 问题内容: 我的页面上有一张表格,其中应该包含某个元素。我可以通过表名(具有唯一的名称)来标识表,并且还可以轻松地标识元素。我想断言元素存在于表的row ,column 上。使用Selenium命令最干净的方法是什么? 备注: 我不想使用除表名以外的其他内容来查找它(我不希望代码中的所有内容)。 我在PHPUnit中使用Selenium。因此,我可以将PHP逻辑用于该任务,尽管我不希望任何复杂的逻