天天看點

如何用 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 檢視實際運作結果,檢視頁面源代碼即可了解實作方法。