WebXR 锚点模块

编辑草案,

关于此文档的更多详细信息
此版本:
https://immersive-web.github.io/anchors/
问题跟踪:
GitHub
规范内嵌
编辑:
(Google)
前任编辑:
(Google)
参与:
提交问题未解决的问题
邮件列表归档
W3C 的 #immersive-web IRC

摘要

描述一种创建由底层系统跟踪的锚点的方法。

本文档的状态

本节描述本文档在发布时的状态。当前 W3C 出版物以及此技术报告最新修订版的列表,可在 W3C 技术 报告索引中找到,地址为 http://www.w3.org/TR/。

本文档由 沉浸式 Web 工作组 作为编辑草案发布。本文档旨在成为 W3C 推荐标准。 欢迎对此规范提供反馈和评论。请使用 Github issues。 讨论也可在 public-immersive-web-wg@w3.org 归档中找到。

作为编辑草案发布并不意味着 W3C 及其成员的认可。本文档是一份草案文档,可能 随时由其他文档更新、替换或废弃。除作为进行中的工作外,不应引用 本文档。

本文档由一个根据 W3C 专利政策运作的小组制作。 W3C 维护一份与该小组交付成果相关的任何 专利 披露的公开列表;该页面还包括 披露专利的说明。任何实际知晓某项专利,且该个人 认为该专利包含 必要 权利要求的个人,都必须按照 W3C 专利政策第 6 节披露该信息。

本文档受 2025年8月18日 W3C 流程文档约束。

1. 简介

WebXR Anchors 模块使应用能够请求底层 XR 系统跟踪某个特定三维姿态(位置和方向)随着系统对世界的理解 变化而发生的改变。这允许应用调整它放置在场景中的虚拟对象的位置, 以有助于维持这些被放置对象真实存在于用户环境中的错觉。

1.1. 术语

在本文档中,姿态表示 3D 空间中的位置和方向。

在本文档中,锚点是一个跟踪相对于真实世界固定的姿态的实体,并由应用创建。

2. 初始化

2.1. 特性描述符

为了让应用在会话期间表示其有意使用锚点,必须使用适当的特性描述符来请求会话。字符串 anchors 由本模块作为锚点特性的新有效 特性描述符引入。

如果设备的跟踪系统暴露原生锚点能力,则设备能够支持锚点特性。内联 XR 设备不得被视为能够 支持锚点特性。用户代理应该尝试为 模式等于 "immersive-ar" 的会话支持锚点特性。

注:尽管不要求支持锚点特性, 但锚点是支持 AR 的应用提供良好用户体验所需的基本特性之一。 因此,*强烈*建议用户代理为 "immersive-ar" 会话支持锚点。

3. 锚点

3.1. XRAnchor

[SecureContext, Exposed=Window]
interface XRAnchor {
  readonly attribute XRSpace anchorSpace;

  Promise<DOMString> requestPersistentHandle();

  undefined delete();
};

XRAnchor 包含 anchorSpace, 可用于相对于其他 XRSpaces 定位锚点。 如果在 已删除设为 true 时访问此属性,用户代理必须抛出 InvalidStateError

每个 XRAnchor 都有一个关联的 已删除布尔值,其初始设置为 false

每个 XRAnchor 都有一个关联的 原生原点

每个 XRAnchor 都有一个关联的 会话

为了从 native originsession 创建 新锚点对象,用户代理必须运行 以下步骤:
  1. anchor 为一个新的 XRAnchor

  2. anchor原生原点设为 native origin

  3. anchor会话设为 session

  4. anchor已删除设为 false

  5. anchoranchorSpace 设为一个新的 XRSpace 对象,该对象以 session 设为 anchor会话native origin 设为原生原点来创建。

  6. 返回 anchor

当在 XRAnchor anchor 上调用 requestPersistentHandle() 方法时,必须运行以下步骤:
  1. promise 为在此 XRSystem相关领域新建的 Promise

  2. 如果 anchor已删除true,则用 InvalidStateError 拒绝 promise, 返回 promise,并中止这些步骤。

  3. sessionanchor会话

  4. 如果 session持久锚点映射包含值 anchor,运行以下步骤:

    1. uuidsession持久锚点映射anchor 值的映射的键。

    2. uuid 解决 promise

    3. 返回 promise

    4. 中止这些步骤。

  5. uuid 为空字符串。

  6. 生成一个 UUID [RFC9562] 作为字符串,并将其附加到 uuid

  7. uuidanchor 添加到 session持久锚点映射

  8. uuid 解决 promise

  9. 返回 promise

注:XRSystem 创建唯一 ID 时,它必须是唯一的,并且只为当前源所知。

4. 锚点创建

XRSession 被扩展为包含一个关联的 被跟踪锚点集

XRSession 被扩展为包含一个关联的 持久 锚点映射,该映射以 UUID 字符串为键,并映射到一个 XRAnchor。 此映射由 XR 设备填充和存储,并且仅限于由 上的任何 XRSession 创建且尚未销毁的持久锚点集合。 此映射的大小由用户代理决定。用户代理可以出于任何原因删除此映射中的条目。 例如,如果所有源的所有映射已达到系统锚点的最大数量, 用户代理可以释放一个条目以便为新请求的锚点腾出空间。

XRSession 被扩展为包含一个关联的 新锚点映射,该映射以 XRAnchor 对象 为键,并映射到 Promise<XRAnchor> 对象。

partial interface XRFrame {
  Promise<XRAnchor> createAnchor(XRRigidTransform pose, XRSpace space);
};

partial interface XRSession {
  readonly attribute FrozenArray<DOMString> persistentAnchors;

  Promise<XRAnchor> restorePersistentAnchor(DOMString uuid);
  Promise<undefined> deletePersistentAnchor(DOMString uuid);
};

partial interface XRHitTestResult {
  Promise<XRAnchor> createAnchor();
};

XRHitTestResult 被扩展为包含一个关联的 原生实体。如果 底层系统未提供有关导致计算该结果的原生实体的信息,则将假定 原生实体设为 null

应用可以通过以下 2 种方式之一创建锚点:

为了从帧创建锚点,应用可以调用 XRFramecreateAnchor(pose, space) 方法。

当在 XRFrame frame 上以 posespace 调用 createAnchor(pose, space) 方法时,必须运行以下步骤:
  1. promise一个新的 Promise

  2. 如果 frameactive 布尔值为 false,则用 InvalidStateError 拒绝 promise, 返回 promise,并中止这些步骤。

  3. sessionframesession

  4. 如果 session帧更新列表中尚不存在 更新锚点 算法,则将其添加到该列表。

  5. devicesessionXR 设备

  6. effective originspace有效原点

  7. anchor native origin 为从 device 调用以使用 pose 创建新锚点所返回的一个新原生原点,该 pose 被解释为在 frame时间相对于 effective origin 表达。

  8. 使用 anchor native originsession 创建新锚点对象 anchor

  9. anchor 添加到 session被跟踪 锚点集

  10. 将从 anchorpromise 的映射添加到 session新锚点映射

  11. 返回 promise

注:用户代理有责任确保 每次 createAnchor(pose, space) 调用返回的锚点所跟踪的物理原点,尽可能接近调用该方法的帧所表示的时间点上 spacepose 的物理位置。具体而言,这意味着对于 动态变化的空间,用户代理应尝试在应用指定的时间捕获此类空间的原生原点。 本文本是非规范性的,但表达了规范作者及贡献者的意图,因此强烈建议 实现遵循它,以确保不同厂商之间的行为一致。

persistentAnchors 返回已知持久锚点的列表。此列表必须反映持久锚点映射的键。
当在 XRSession session 上以 uuid 调用 restorePersistentAnchor(uuid) 方法时,必须运行以下步骤:
  1. promise 为在此 XRSystem相关领域新建的 Promise

  2. 如果 session持久锚点映射不包含 从 uuidXRAnchor 的映射, 则用 InvalidStateError 拒绝 promise, 返回 promise,并中止这些步骤。

  3. 如果 sessionended 值为 `true`,则用 InvalidStateError 拒绝 promise, 返回 promise,并中止这些步骤。

  4. anchorsession持久锚点映射上 来自 uuid 的映射的值。

  5. 如果 session新锚点映射包含从 anchorpromise 的映射,则用 InvalidStateError 拒绝promise, 返回 promise,并中止这些步骤。

  6. 如果 session新锚点映射已达到用户代理 最大大小,则用 InvalidStateError 拒绝 promise, 返回 promise,并中止这些步骤。

  7. anchor 添加到 session被跟踪 锚点集

  8. 将从 anchorpromise 的映射添加到 session新锚点映射

  9. 返回 promise

当在 XRSession session 上以 uuid 调用 deletePersistentAnchor() 方法时,必须运行以下步骤:
  1. promise 为在此 XRSystem相关领域新建的 Promise

  2. 如果 session持久锚点映射不包含 到 anchor 的映射,则用 InvalidStateError 拒绝 promise, 返回 promise,并中止这些步骤。

  3. anchorsession持久锚点映射上 来自 uuid 的映射的值。

  4. session持久锚点映射中移除该映射。

  5. anchor 上调用 delete()

  6. 返回 promise

为了从命中测试结果创建锚点,应用 可以调用 XRHitTestResultcreateAnchor() 方法。

当在 XRHitTestResult hitTestResult 上调用 createAnchor() 方法时,必须运行以下步骤:
  1. promise一个新的 Promise

  2. framehitTestResultframe

  3. 如果 frameactive 布尔值为 false,则用 InvalidStateError 拒绝 promise, 返回 promise,并中止这些步骤。

  4. sessionframesession

  5. 如果 session帧更新列表中尚不存在 更新 锚点算法,则将其添加到该列表。

  6. devicesessionXR 设备

  7. nativeEntityhitTestResult原生 实体

  8. anchor native origin 为从 device 调用以创建新锚点所返回的新原生原点, 该新锚点位于 hitTestResult原生原点,并在 frame时间附加nativeEntity

  9. 使用 anchor native originsession 创建新锚点对象 anchor

  10. anchor 添加到 session被跟踪 锚点集

  11. 将从 anchorpromise 的映射添加到 session新锚点映射

  12. 返回 promise

注:存在于 createAnchor(pose, space) 方法上的相同说明同样适用于此处。

Session 的“帧更新列表” 可能需要一种指定顺序的方式——某些算法可能依赖其他算法。

5. 锚点更新

[Exposed=Window]
interface XRAnchorSet {
  readonly setlike<XRAnchor>;
};

partial interface XRFrame {
  [SameObject] readonly attribute XRAnchorSet trackedAnchors;
};

XRAnchorSet 接口被引入,用作暴露锚点集合的一种方式。

XRFrame 被扩展为包含 trackedAnchors 属性,该属性包含帧中仍被跟踪的所有锚点。在 XRFrame 创建时,该集合初始为空,并将由更新锚点算法填充。

为了为 frame 更新 锚点,用户代理必须运行以下步骤:
  1. sessionframesession

  2. devicesessionXR 设备

  3. 对于 session被跟踪 锚点集中的每个 anchor,运行:

    1. 查询 device 的跟踪系统以获取 anchor原生原点信息。

    2. 如果 device 的跟踪系统不再跟踪anchor,则运行 以下步骤:

      1. session被跟踪锚点集中移除 anchor

      2. 如果 session新锚点映射包含从 anchorpromise 的映射,则 拒绝promise 并移除该 映射。

      3. 继续处理 session被跟踪锚点集中的下一个条目。

    3. anchor 添加到 frametrackedAnchors 集合。

    4. 如果 session新锚点映射包含从 anchorpromise 的映射,则用 anchor 解决promise 并移除该映射。

6. 锚点移除

当应用不再有兴趣接收某个锚点的更新时,它可以通过调用 delete()删除锚点

当在 XRAnchor anchor 上调用 delete() 方法时,必须通过运行以下步骤来删除锚点
  1. 如果 anchor已删除true,则中止这些步骤。

  2. anchoranchorSpace 设为 null

  3. anchor已删除设为 true

  4. sessionanchorsession

  5. devicesessionXR 设备

  6. native originanchor原生原点

  7. 通知 device 的跟踪系统不再跟踪该 native origin

  8. session被跟踪 锚点集中移除 anchor

7. 原生设备概念

为了使用户代理能够实现锚点 API,底层 XR 设备应对此特性提供原生支持。 本节描述对底层 XR 系统提出的要求,并且为使锚点 API 能够在各种 框架/设备之上实现,必然规定得不够详细。

7.1. 原生锚点

如果底层 XR 设备支持以下与锚点相关的能力,则它能够 支持anchors 特性:

如果底层设备不支持原生锚点,用户代理可以决定通过仿真原生锚点来实现 锚点 API。此方法假定锚点一经创建便永远不会改变其姿态,并且其姿态就是应用传入锚点 创建方法的姿态,例如 XRFramecreateAnchor(pose, space)XRHitTestResultcreateAnchor()

注:仿真原生锚点 方法等价于应用自行仿真锚点特性,并且可以帮助减少应用需要处理的不同情况数量。 它还可能允许应用为 "immersive-ar""immersive-vr" 会话复用相同代码。

8. 隐私与安全考量

锚点 API 不会直接暴露对用户环境信息的访问。如果会话创建时启用了 hit-test 支持, 并且设备支持跟踪移动对象,则应用可能能够通过观察对象(例如被携带移动的对象)的 锚点姿态变化来推断用户环境的布局。这提供的信息级别与 命中测试 API 关于用户环境的信息类似。锚点特性在创建 XR 会话时必须声明, 这将允许用户代理通知用户允许网站使用锚点 API 的潜在隐私影响。

我不知道有支持跟踪 移动的一般对象的设备——规范是否应该考虑它们?是否有这类设备的示例?

9. 致谢

以下个人为 WebXR Anchors 规范的设计做出了贡献:

一致性

文档 约定

一致性要求通过描述性断言 与 RFC 2119 术语的组合来表达。 关键词“MUST”、“MUST NOT”、“REQUIRED”、“SHALL”、“SHALL NOT”、“SHOULD”、“SHOULD NOT”、“RECOMMENDED”、 “MAY”和“OPTIONAL” 在本文档的规范性部分中 应按 RFC 2119 中所述进行解释。 但是,为了可读性, 这些词在本规范中并不全部以大写字母出现。

除明确标记为非规范性的章节、示例和注释外, 本规范的所有文本均为规范性的。[RFC2119]

本规范中的示例以“例如”一词引入, 或通过 class="example" 与规范性文本区分开来, 如下所示:

这是一个资料性示例的示例。

资料性注释以“注”一词开头, 并通过 class="note" 与规范性文本区分开来, 如下所示:

注,这是一个资料性注释。

一致性 算法

作为算法的一部分以祈使句表述的要求 (例如“去除任何前导空格字符” 或“返回 false 并中止这些步骤”), 应按照引入该算法时使用的关键词 (“must”、“should”、“may”等) 的含义进行解释。

以算法或具体步骤形式表述的一致性要求 可以以任何方式实现, 只要最终结果等价即可。 特别是,本规范中定义的算法 旨在易于理解, 并非旨在具备高性能。 鼓励实现者进行优化。

索引

由本 规范定义的术语

由引用 定义的术语

引用

规范性引用

[HTML]
Anne van Kesteren; et al. HTML 标准. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[RFC2119]
S. Bradner. 用于在 RFC 中 指示要求级别的关键词. March 1997. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[RFC9562]
K. Davis; B. Peabody; P. Leach. 通用唯一 标识符(UUID). May 2024. Proposed Standard. URL: https://www.rfc-editor.org/rfc/rfc9562
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL 标准. Living Standard. URL: https://webidl.spec.whatwg.org/
[WEBXR]
Brandon Jones; Manish Goregaokar; Rik Cabanier. WebXR 设备 API. URL: https://immersive-web.github.io/webxr/
[WEBXR-AR-MODULE-1]
Brandon Jones; Manish Goregaokar; Rik Cabanier. WebXR 增强现实模块 - Level 1. URL: https://immersive-web.github.io/webxr-ar-module/

IDL 索引

[SecureContext, Exposed=Window]
interface XRAnchor {
  readonly attribute XRSpace anchorSpace;

  Promise<DOMString> requestPersistentHandle();

  undefined delete();
};

partial interface XRFrame {
  Promise<XRAnchor> createAnchor(XRRigidTransform pose, XRSpace space);
};

partial interface XRSession {
  readonly attribute FrozenArray<DOMString> persistentAnchors;

  Promise<XRAnchor> restorePersistentAnchor(DOMString uuid);
  Promise<undefined> deletePersistentAnchor(DOMString uuid);
};

partial interface XRHitTestResult {
  Promise<XRAnchor> createAnchor();
};

[Exposed=Window]
interface XRAnchorSet {
  readonly setlike<XRAnchor>;
};

partial interface XRFrame {
  [SameObject] readonly attribute XRAnchorSet trackedAnchors;
};

问题索引

Session 的“帧更新列表”可能需要一种指定顺序的方式——某些 算法可能依赖其他算法。
我不知道有支持跟踪移动的一般对象的设备——规范是否应当 考虑它们?是否有这类设备的示例?
MDN

XRAnchor/anchorSpace

In only one current engine.

FirefoxNoneSafariNoneChrome85+
Opera?Edge85+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRAnchor/delete

In only one current engine.

FirefoxNoneSafariNoneChrome85+
Opera?Edge85+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRAnchor

In only one current engine.

FirefoxNoneSafariNoneChrome85+
Opera?Edge85+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRAnchorSet

In only one current engine.

FirefoxNoneSafariNoneChrome85+
Opera?Edge85+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRFrame/createAnchor

In only one current engine.

FirefoxNoneSafariNoneChrome85+
Opera?Edge85+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRFrame/trackedAnchors

In only one current engine.

FirefoxNoneSafariNoneChrome85+
Opera?Edge85+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?
MDN

XRHitTestResult/createAnchor

In only one current engine.

FirefoxNoneSafariNoneChrome85+
Opera?Edge85+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebViewNoneSamsung Internet?Opera Mobile?