天天看点

如何用 javascript 获取布局中的文本尺寸和坐标

作者:一米六五的神喃

今年早些时候碰到了一个需求:获取一个页面中所有的元素的坐标信息,除此之外还需要获取页面中的所有文本的坐标和尺寸。

前半部分的需求比较常规,可以通过遍历整个文档来获取所有的元素,再通过元素的 getBoundingClientRect() 方法即可取得。后半部分的文本的获取则有些困难,因为文本本身是通过: <tag>text<tag> 的方式存在的,而文本自身则不是一个 DOM 元素。

如何用 javascript 获取布局中的文本尺寸和坐标

text-in-paragraph

假设我们有一个元素 p,其中放置了一段文本,如果通过 p 元素的 getBoundingClientRect() 方法则只能获取 p 元素的坐标和尺寸,并且这个尺寸还会受到 CSS 属性的影响,比如 width,height,padding 等等。

至此,问题就分成了两个部分:

  1. 如何从元素中找到文本
  2. 如何获取文本的尺寸和坐标

突然灵光一闪,依稀记得元素中似乎有个 childNodes 属性,打印出来一看果然没错,文本确实就在 childNodes 里,体现为一个文本 node,并且文本类型是特殊的,表现为 nodeType 为 3。这个思路有了之后,第一个问题基本解决。

既然已经得到了文本 node,那么是不是直接使用 getBoundingClientRect() 就可以得到文本的尺寸和坐标了呢?答案是否定的。查了一下 MDN 中关于 getBoundingClientRect() 的解释,发现只有 Range 和 Element 可以使用,但文本 node 既不是 Element 也不是 Range。别急,Range?那我为这个文本 node 创建一个 Range 可不可以?我按照这个思路继续尝试。

先创建一个 Range

1
           
const range = document.createRange()
           

然后让这个 Range 选中已经找到的文本 node

1
           
range.selectNode(node)
           

这个时候再通过 range 的 getBoundingClientRect() 获取坐标和尺寸

1
           
range.getBoundingClientRect() // 获取 range 的 rect 信息
           

不出所料,果然获取到了文本的坐标和尺寸。

测试的页面看起来是这样:

如何用 javascript 获取布局中的文本尺寸和坐标

text-in-page

实际获取的所有文本结果:

如何用 javascript 获取布局中的文本尺寸和坐标

measure-result

可以访问 DEMO 查看实际运行结果,查看页面源代码即可了解实现方法。