介绍 getBoxQuads API

Web 开发人员经常需要确定元素在页面中的位置,或者更普遍地说,它相对于另一个元素的位置。现有的执行此操作的 API 存在重大限制。新的 GeometryUtils 接口及其支持的接口 DOMPointDOMRectDOMQuad 提供了 Web 标准 API 来解决这些问题。Firefox 是第一个实现这些 API 的浏览器;它们在 Firefox 31 Nightly 版本中可用。

检索元素几何图形的当前最佳标准化 API

目前,检索元素几何图形的最佳标准化 DOM API 是 element.getBoundingClientRect()element.getClientRects()。这些返回相对于包含文档的视口元素的边框框矩形。这些 API 跨浏览器受支持,但存在一些限制

  • 当存在复杂的 CSS 变换时,它们会返回包含变换边框框的最小轴对齐矩形。这会丢失信息。
  • 无法获取内容框、填充框或边框框的坐标。在简单的情况下,您可以从 getBoundingClientRect()/getClientRects() 的结果中添加或减去计算出的样式值,但这很笨拙且难以正确实现。例如,当 <span> 分成几个片段时,它的左边界仅添加到其中一个片段中——第一个或最后一个,具体取决于文本的方向性。
  • 无法获取相对于另一个元素的框几何图形。

介绍 getBoxQuads()

GeometryUtils.getBoxQuads() 方法在 DocumentElementTextNode 上实现,解决了这些问题。它返回一个 DOMQuad 列表,每个 CSS 片段一个(通常此列表只有一个
DOMQuad).

示例

var quads = document.getElementById("d").getBoxQuads();
// quads.length == 1
// quads[0].p1.x == 100
// quads[0].p1.y == 100
// quads[0].p3.x == 200
// quads[0].p3.y == 200
p1
p2
p3
p4

使用边界

DOMQuad 是四个 DOMPoint 的集合,定义了任意四边形的角。返回 DOMQuad 使 getBoxQuads() 即使在存在任意 2D 或 3D 变换时也能返回准确的信息。它有一个方便的 bounds 属性,在您只需要轴对齐边界矩形的情况下返回 DOMRectReadOnly

例如

var quads = document.getElementById("d").getBoxQuads();
// quads[0].p1.x == 150
// quads[0].p1.y == 150 - 50*sqrt(2) (approx)
// quads[0].p3.x == 150
// quads[0].p3.y == 150 + 50*sqrt(2) (approx)
// quads[0].bounds.width == 100*sqrt(2) (approx)
p1
p2
p3
p4
bounds

传入选项

默认情况下,getBoxQuads() 返回相对于节点文档视口的边框框,但这可以通过传入一个可选的
包含以下(可选)成员的选项字典来自定义

  • box"content""padding""border""margin" 之一,选择要返回的 CSS 框类型。
  • relativeToDocumentElementTextNodegetBoxQuads() 返回相对于该节点边框框左上角的坐标(如果有多个片段,则为第一个片段的边框框)。对于文档,使用文档视口的原点。

示例

var quads = document.getElementById("e").getBoxQuads({
  relativeTo:document.getElementById("d")
});
// quads[0].p1.x == 0
// quads[0].p1.y == 0

quads = document.getElementById("e").getBoxQuads({
  relativeTo:document.getElementById("d"),
  box:"content"
});
// quads[0].p1.x == 20
// quads[0].p1.y == 20
d
e 内容框
e 边界框

relativeTo 节点不必是接收 getBoxQuads() 的节点的祖先。这些节点甚至可以在不同的文档中,尽管它们必须位于相同的最顶层浏览上下文(即浏览器选项卡)中。

浅尝辄止

如果您读到这里,您可能已经足够敏锐地注意到 GeometryUtils 中的其他方法——用于坐标转换的方法。这些将在以后的博文中介绍。

关于 roc

Robert O'Callahan 是 Mozilla 公司的杰出工程师。在加入 MoCo 之前,他多年来一直是 Mozilla 的志愿者贡献者(自 2000 年起)。

roc 的更多文章…

关于 Robert Nyman [荣誉编辑]

技术布道师和 Mozilla Hacks 编辑。发表关于 HTML5、JavaScript 和开放网络的演讲和博客文章。Robert 是 HTML5 和开放网络的坚定支持者,自 1999 年以来一直在从事 Web 前端开发工作——在瑞典和纽约市。他还定期在 http://robertnyman.com 上发布博客文章,并且喜欢旅行和结识新朋友。

Robert Nyman [荣誉编辑] 的更多文章…


10 条评论

  1. Aditya Bhatt

    这看起来太棒了,在 WebODF 就绪后应该会非常有用。:-)
    是否有在某个地方维护良好的 polyfill?

    2014 年 3 月 27 日 03:04

    1. Robert Nyman [编辑]

      目前还没有意识到任何 polyfill,以及如何在该上下文中使用/工作。

      2014 年 3 月 28 日 07:52

  2. PhistucK

    请,请,请,不要鼓励开发人员根据其 ID 将元素作为全局变量引用。要么使用 document.querySelector(“#d”) 或其他方法,永远不要鼓励开发人员只使用“d”。
    你能修复这些示例吗?

    2014 年 3 月 27 日 12:48

    1. Robert Nyman [编辑]

      好的,我已更新了文章。

      2014 年 3 月 28 日 09:57

      1. PhistucK

        太好了,谢谢!

        2014 年 3 月 28 日 09:59

  3. Aras

    很酷的东西!这将非常有用。我经常希望有一种方法可以监听 DOM 元素边界的变化。这方面是否有进展?

    2014 年 3 月 27 日 15:52

    1. Robert O’Callahan

      没有,这是一个单独的问题(但很重要!)。

      2014 年 3 月 28 日 08:31

  4. Mikael Gramont

    “[getBoxQuads] 返回一个 DOMQuad 列表,每个 CSS 片段一个(通常此列表只有一个 DOMQuad)。"

    我不熟悉 CSS 片段的概念。什么时候会返回多个 DOMQuad?

    2014 年 4 月 2 日 21:47

    1. thinsoldier

      我认为当您有一个跨多行换行的 span 或文本节点时。每一行都是一个单独的矩形。

      2014 年 4 月 3 日 14:27

      1. Robert O’Callahan

        是的。如果您有一个跨多列的 CSS 块也是如此。还有其他情况。

        2014 年 4 月 10 日 21:00

本文的评论已关闭。