1. 引言
本节是非规范性的。
本规范提供了两个新的 DOM 事件,用于获取有关宿主设备物理方向和运动的信息。这些事件提供的信息并非原始传感器数据,而是与底层信息源无关的高级数据。常见的信息源包括陀螺仪、罗盘和加速度计。
deviceorientation 事件表示设备的物理方向,表现为从局部坐标系进行的一系列旋转。
devicemotion 事件表示设备的加速度,以设备定义的笛卡尔坐标系表示。它还提供了设备围绕局部坐标系的旋转速率。在实际可行的情况下,该事件应提供设备质心的加速度。
以下代码摘录展示了这些事件的基本用法。
deviceorientation 事件window. addEventListener( "deviceorientation" , event=> { // process event.alpha, event.beta and event.gamma }); // Alternatively... window. ondeviceorientation= event=> { // process event.alpha, event.beta and event.gamma };
{ alpha: 90 , beta: 0 , gamma: 0 };
要获得罗盘方位,只需用 360 度减去 alpha。当设备在水平面上转动时,罗盘方位为 (360 - alpha)。
devicemotion 事件window. addEventListener( "devicemotion" , ( event) => { // Process event.acceleration, event.accelerationIncludingGravity, // event.rotationRate and event.interval }); // Alternatively... window. ondevicemotion= ( event) => { // Process event.acceleration, event.accelerationIncludingGravity, // event.rotationRate and event.interval };
acceleration 和 accelerationIncludingGravity 的正 x 分量。设备还记录了 rotationRate 的负值。gamma{ acceleration: { x: v^ 2 / r, y: 0 , z: 0 }, accelerationIncludingGravity: { x: v^ 2 / r, y: 9.8 , z: 0 }, rotationRate: { alpha: 0 , beta: 0 , gamma: - v/ r* 180 / pi} };
2. 范围
本节是非规范性的。
本规范的范围包括表示宿主设备物理方向和运动的事件。超出范围的是用于操作方向数据的工具(例如变换库)、提供对原始传感器数据的访问,或直接与这些传感器交互的方法。
3. 模型
3.1. 设备方向
本规范将设备的物理方向表示为相对于 实现定义 参考坐标系的一系列旋转。
旋转步骤序列是一组 Z - X' - Y'' 型内禀 Tait-Bryan 角 ([EULERANGLES]),应用于 [ACCELEROMETER] 中定义并总结如下的 设备坐标系
-
x 轴位于屏幕或键盘平面内,且在屏幕或键盘右侧方向为正。
-
y 轴位于屏幕或键盘平面内,且在屏幕或键盘顶部方向为正。
-
z 轴垂直于屏幕或键盘,且指向屏幕或键盘外部方向为正。
对于手机或平板电脑等移动设备,设备坐标系是相对于标准方向(通常为竖屏)的屏幕定义的。这意味着滑出式组件(如键盘)未展开,且旋转式组件(如显示屏)折叠至其默认位置。
如果设备旋转时屏幕方向发生变化或部署了滑出式键盘,这不会影响坐标系相对于设备的方向。
对于笔记本电脑,设备坐标系是相对于集成键盘定义的。
注意: 希望检测屏幕方向变化的开发者可以参考 [SCREEN-ORIENTATION]。
旋转使用右手约定,即沿轴的正向观察时,绕轴的正向旋转为顺时针方向。
注意: 本规范使用的坐标系与 CSS Transforms 2 § 4 变换渲染模型 不同,在该模型中 y 轴在下方为正,且旋转遵循左手约定。此外,[GEOMETRY-1] 中指定的 rotateSelf() 和 rotate() 以 Z - Y' - X'' 顺序应用旋转,这与此处指定的顺序不同。
由 alpha、beta 和 gamma 表示的旋转通过以下步骤执行
-
将设备框架绕其 z 轴旋转
alpha度,其中alpha在 [0, 360) 范围内。
设备处于初始位置,参考框架 (XYZ) 与主体框架 (xyz) 对齐。
设备绕 z 轴旋转 alpha 角,x 和 y 轴的先前位置显示为 x0 和 y0。 -
将设备框架绕其 x 轴旋转
beta度,其中beta在 [-180, 180) 范围内。
设备绕新 x 轴旋转 beta 角,y 和 z 轴的先前位置显示为 y0 和 z0。 -
将设备框架绕其 y 轴旋转
gamma度,其中gamma在 [-90, 90) 范围内。
设备绕新 y 轴旋转 gamma 角,x 和 z 轴的先前位置显示为 x0 和 z0。
注意: 此角度选择遵循数学约定,但意味着 alpha 的方向与罗盘方位相反。这也意味着这些角度与车辆动力学中使用的滚转-俯仰-偏航约定不匹配。
3.1.1. 参考坐标系的选择
设备的方向总是相对于另一个坐标系,其选择会影响方向所传达的信息类型以及方向数据的来源。
相对设备方向 使用加速度计和陀螺仪测量,参考坐标系是任意的。因此,方向数据提供有关相对于设备初始位置的变化信息。
注意: 在原生平台术语中,这类似于 Windows 上的相对 OrientationSensor、Android 上的 游戏旋转矢量传感器,或 Core Motion 的 xArbitraryZVertical 选项。
绝对方向 使用加速度计、陀螺仪和磁力计测量,参考坐标系是 地球参考坐标系。
注意: 在原生平台术语中,这类似于 Windows 上的绝对 OrientationSensor、Android 上的 旋转矢量传感器,或 Core Motion 的 xMagneticNorthZVertical 选项。
3.2. 设备运动
本规范通过测量设备的加速度和旋转速率(从加速度计和陀螺仪获得)来表示设备在空间中的运动。数据是相对于上一节中总结的 设备坐标系 提供的。
加速度是设备速度随时间的变化率。以米每二次方秒 (m/s2) 表示。
线性设备加速度 表示设备在没有重力贡献的情况下的加速度。当设备平放在桌子上时,其 线性加速度 为 0 m/s2。
当加速度 包含重力 时,其值包括重力的影响并表示固有加速度 ([PROPERACCELERATION])。当设备处于自由落体状态时,加速度为 0 m/s2。这在许多应用中不太有用,但它是为无法提供 线性加速度(例如由于缺乏陀螺仪)的实现提供的一种尽力而为的支持方式。
注意: 在实践中,包含重力的加速度 表示从 运动传感器解释 § 加速度计 获得的原始读数,或 [G-FORCE],而 线性加速度 提供 运动传感器解释 § 线性加速度传感器 的读数,且很可能是融合传感器。[MOTION-SENSORS] 和 [ACCELEROMETER] 均包含关于不同类型加速度计和可测量加速度的更详细讨论。
旋转速率 测量设备围绕 设备坐标系 中指定轴的旋转速率。与设备方向一样,旋转必须使用右手约定,即沿轴的正向观察时,绕轴的正向旋转为顺时针方向。旋转速率 以度每秒 (deg/s) 为单位测量。
注意: [MOTION-SENSORS] 和 [GYROSCOPE] 均包含关于陀螺仪、旋转速率和测量的更详细讨论。
4. 权限
DeviceMotionEvent.requestPermission() 和 DeviceOrientationEvent.requestPermission() 测试的通过率较低,此集成被标记为 处于风险。本规范是一项 强大功能,因此它定义了以下 权限,这些权限是带有给定 默认允许列表 的 策略控制功能
-
在提供 相对方向 数据时,仅当 "accelerometer" 和 "gyroscope" 权限 被 授予 时,deviceorientation 事件才会被 分发。为了让实现回退到 绝对方向 数据,还必须 授予 "magnetometer" 权限。
-
仅当 "accelerometer"、"gyroscope" 和 "magnetometer" 权限 被 授予 时,deviceorientationabsolute 事件才会被 分发。
-
仅当 "accelerometer" 和 "gyroscope" 权限 被 授予 时,devicemotion 事件才会被 分发。
5. 任务源
本规范中提及的 任务 的 任务源 是 设备运动和方向任务源。
6. API
6.1. deviceorientation 事件
partial interface Window { [SecureContext ]attribute EventHandler ondeviceorientation ; }; [Exposed =Window ,SecureContext ]interface :DeviceOrientationEvent Event {(constructor DOMString ,type optional DeviceOrientationEventInit = {});eventInitDict readonly attribute double ?alpha ;readonly attribute double ?beta ;readonly attribute double ?gamma ;readonly attribute boolean absolute ;static Promise <PermissionState >requestPermission (optional boolean =absolute false ); };dictionary :DeviceOrientationEventInit EventInit {double ?=alpha null ;double ?=beta null ;double ?=gamma null ;boolean =absolute false ; };
ondeviceorientation 属性是 ondeviceorientation 事件处理程序 的 事件处理程序 IDL 属性,其 事件处理程序事件类型 为 deviceorientation。
alpha 属性必须返回其初始化时的值。它表示 § 3.1 设备方向 中描述的 Z - X' - Y'' 内禀 Tait-Bryan 角绕 Z 轴的旋转。
beta 属性必须返回其初始化时的值。它表示 § 3.1 设备方向 中描述的 Z - X' - Y'' 内禀 Tait-Bryan 角绕 X' 轴(在绕 Z 轴旋转之后产生)的旋转。
gamma 属性必须返回其初始化时的值。它表示 § 3.1 设备方向 中描述的 Z - X' - Y'' 内禀 Tait-Bryan 角绕 Y'' 轴(按此顺序绕 Z 和 X' 轴旋转之后产生)的旋转。
absolute 属性必须返回其初始化时的值。它指示正在提供的是 相对方向 数据还是 绝对方向 数据。
requestPermission(absolute) 方法的步骤如下-
令 global 为 当前全局对象。
-
如果 此 对象的 相关全局对象 具有 瞬时激活,则令 hasTransientActivation 为 true,否则为 false。
-
令 promise 为 此 对象的 相关 Realm 中的 一个新 promise。
-
令 permissions 为 « "accelerometer", "gyroscope" »。
-
如果 absolute 为 true,将 "magnetometer" 追加 到 permissions。
-
以并行方式运行这些步骤
-
-
如果 name 的 权限状态 为 "
prompt" 且 hasTransientActivation 为 false-
在 设备运动和方向任务源 上排队一个全局任务,给定 global,以 "
NotAllowedError"DOMException拒绝 promise。 -
返回。
-
-
-
令 permissionState 为 "
granted"。 -
注意: 没有一次性请求多个权限的算法。然而,鼓励用户代理将针对不同媒体类型的并发请求捆绑到一个面向用户的权限提示中。
-
在 设备运动和方向任务源 上排队一个全局任务,给定 global,以 permissionState 解析 promise。
-
-
返回 promise。
DOMString event、Window window 和 boolean absolute,触发方向事件-
令 orientation 为 null。
-
如果 absolute 为 false,则令 virtualSensorType 为 "
relative-orientation",否则为 "absolute-orientation"。 -
否则
-
令 permissions 为 null。
-
如果 absolute 为 false
-
将 permissions 设置为 « "accelerometer", "gyroscope" »。
-
-
否则
-
将 permissions 设置为 « "accelerometer", "gyroscope", "magnetometer" »。
-
-
令 environment 为 window 的 相关设置对象。
-
并行 执行这些步骤
-
在 设备运动和方向任务源 上排队一个全局任务,给定 window,以执行以下步骤
-
令 z 为 orientation 表示为沿 Z 轴的内禀 Tait-Bryan 角 Z - X' - Y'' 的值,如果实现无法提供角度值,则为 null。
-
如果 z 不为 null,将 z 的精度限制为 0.1 度。
-
令 x 为 orientation 表示为沿 X' 轴的内禀 Tait-Bryan 角 Z - X' - Y'' 的值,如果实现无法提供角度值,则为 null。
-
如果 x 不为 null,将 x 的精度限制为 0.1 度。
-
令 y 为 orientation 表示为沿 Y'' 轴的内禀 Tait-Bryan 角 Z - X' - Y'' 的值,如果实现无法提供角度值,则为 null。
-
如果 y 不为 null,将 y 的精度限制为 0.1 度。
-
在 window 上 触发 一个名为 event 的事件,使用
DeviceOrientationEvent,其中alpha属性初始化为 z,beta属性初始化为 x,gamma属性初始化为 y,并且absolute属性初始化为 absolute。
-
方向的 重大变化 指示与前一个值相比,方向值的差异足以触发 deviceorientation 或 deviceorientationabsolute 事件。确定是否发生了 方向的重大变化 的过程是 实现定义 的,尽管建议将 1 度作为变化的最高阈值。如果实现有理由相信页面没有足够新鲜的数据,它们也可以考虑发生了该变化。
注意: 实现必须考虑 § 9 自动化 来确定是否发生了 方向的重大变化,以便虚拟传感器读数更新导致其被评估。
-
令 document 为 window 的 关联文档。
-
如果 document 的 可见性状态 不是
"visible",则返回。 -
令 absolute 为 false。
-
令 features 为 « "accelerometer", "gyroscope" »。
-
如果实现无法提供 相对方向,或者由此产生的 绝对方向 数据更准确
-
将 absolute 设置为 true。
-
追加 "magnetometer" 到 features。
-
-
-
如果 document 不被 允许使用 feature,则返回。
-
-
触发方向事件,使用 deviceorientation、window 和 absolute。
如果实现永远无法提供方向信息,则应触发事件,并将 alpha、beta 和 gamma 属性设置为 null,并将 absolute 属性设置为 false。
6.2. deviceorientationabsolute 事件
partial interface Window { [SecureContext ]attribute EventHandler ondeviceorientationabsolute ; };
ondeviceorientationabsolute 属性是 ondeviceorientationabsolute 事件处理程序 的 事件处理程序 IDL 属性,其 事件处理程序事件类型 为 deviceorientationabsolute。
deviceorientationabsolute 事件与 deviceorientation 事件完全类似,不同之处在于它必须始终提供 绝对方向 数据。
-
触发方向事件,使用 deviceorientationabsolute、window 和 true。
如果实现永远无法提供绝对方向信息,则应触发事件,并将 alpha、beta 和 gamma 属性设置为 null,并将 absolute 属性设置为 true。
6.3. devicemotion 事件
6.3.1. The DeviceMotionEventAcceleration 接口
[Exposed =Window ,SecureContext ]interface {DeviceMotionEventAcceleration readonly attribute double ?x ;readonly attribute double ?y ;readonly attribute double ?z ; };
DeviceMotionEventAcceleration 接口表示 § 3.2 设备运动 中描述的设备加速度。它具有以下相关数据
- x 轴加速度
-
设备沿 X 轴的加速度,或 null。初始为 null。
- y 轴加速度
-
设备沿 Y 轴的加速度,或 null。初始为 null。
- z 轴加速度
-
设备沿 Z 轴的加速度,或 null。初始为 null。
6.3.2. The DeviceMotionEventRotationRate 接口
[Exposed =Window ,SecureContext ]interface {DeviceMotionEventRotationRate readonly attribute double ?alpha ;readonly attribute double ?beta ;readonly attribute double ?gamma ; };
DeviceMotionEventRotationRate 接口表示 § 3.2 设备运动 中描述的设备 旋转速率。它具有以下相关数据
- x 轴旋转速率
-
设备绕 X 轴的旋转速率,或 null。初始为 null。
- y 轴旋转速率
-
设备绕 Y 轴的旋转速率,或 null。初始为 null。
- z 轴旋转速率
-
设备绕 Z 轴的旋转速率,或 null。初始为 null。
alpha 获取器的步骤是返回 此 对象的 x 轴旋转速率 的值。
beta 获取器的步骤是返回 此 对象的 y 轴旋转速率 的值。
gamma 获取器的步骤是返回 此 对象的 z 轴旋转速率 的值。
6.3.3. The DeviceMotionEvent 接口
partial interface Window { [SecureContext ]attribute EventHandler ondevicemotion ; }; [Exposed =Window ,SecureContext ]interface :DeviceMotionEvent Event {(constructor DOMString ,type optional DeviceMotionEventInit = {});eventInitDict readonly attribute DeviceMotionEventAcceleration ?acceleration ;readonly attribute DeviceMotionEventAcceleration ?accelerationIncludingGravity ;readonly attribute DeviceMotionEventRotationRate ?rotationRate ;readonly attribute double interval ;static Promise <PermissionState >requestPermission (); };dictionary {DeviceMotionEventAccelerationInit double ?=x null ;double ?=y null ;double ?=z null ; };dictionary {DeviceMotionEventRotationRateInit double ?=alpha null ;double ?=beta null ;double ?=gamma null ; };dictionary :DeviceMotionEventInit EventInit {DeviceMotionEventAccelerationInit ;acceleration DeviceMotionEventAccelerationInit ;accelerationIncludingGravity DeviceMotionEventRotationRateInit ;rotationRate double = 0; };interval
ondevicemotion 属性是 ondevicemotion 事件处理程序 的 事件处理程序 IDL 属性,其 事件处理程序事件类型 为 devicemotion。
acceleration 属性必须返回其初始化时的值。创建对象时,该属性必须初始化为 null。它表示设备的 线性加速度。
accelerationIncludingGravity 属性必须返回其初始化时的值。创建对象时,该属性必须初始化为 null。它表示设备的 包含重力的加速度。
rotationRate 属性必须返回其初始化时的值。创建对象时,该属性必须初始化为 null。它表示设备的 旋转速率。
interval 属性必须返回其初始化时的值。它表示从底层硬件获取数据的间隔,必须以毫秒 (ms) 为单位表示。它是常数,旨在简化 Web 应用程序对数据的过滤。
requestPermission() 方法的步骤如下-
令 global 为 当前全局对象。
-
如果 此 对象的 相关全局对象 具有 瞬时激活,则令 hasTransientActivation 为 true,否则为 false。
-
令 result 为 此 对象的 相关 Realm 中的 一个新 promise。
-
并行 执行这些步骤
-
令 permissions 为 « "accelerometer", "gyroscope" »。
-
-
如果 name 的 权限状态 为 "
prompt" 且 hasTransientActivation 为 false-
在 设备运动和方向任务源 上排队一个全局任务,给定 global,以 "
NotAllowedError"DOMException拒绝 result。 -
返回。
-
-
-
令 permissionState 为 "
granted"。 -
注意: 没有一次性请求多个权限的算法。然而,鼓励用户代理将针对不同媒体类型的并发请求捆绑到一个面向用户的权限提示中。
-
在 设备运动和方向任务源 上排队一个全局任务,给定 global,以 permissionState 解析 result。
-
-
返回 result。
-
令 document 为 window 的 关联文档。
-
如果 document 的 可见性状态 不是
"visible",则返回。 -
对于 « "accelerometer", "gyroscope" » 中的 每个 policy
-
令 platformLinearAcceleration 为 null。
-
否则,如果实现能够提供 线性加速度
-
将 platformLinearAcceleration 设置为设备沿 X、Y 和 Z 轴的 线性加速度。
-
-
令 acceleration 为 null。
-
如果 platformLinearAcceleration 不为 null
-
将 acceleration 设置为在 window 的 Realm 中创建的 新
DeviceMotionEventAcceleration。 -
将 acceleration 的 x 轴加速度 设置为 platformLinearAcceleration 沿 X 轴的值,或者如果无法提供则为 null。
-
如果 acceleration 的 x 轴加速度 不为 null,则将其精度限制为不超过 0.1 m/s2。
-
将 acceleration 的 y 轴加速度 设置为 platformLinearAcceleration 沿 Y 轴的值,或者如果无法提供则为 null。
-
如果 acceleration 的 y 轴加速度 不为 null,则将其精度限制为不超过 0.1 m/s2。
-
将 acceleration 的 z 轴加速度 设置为 platformLinearAcceleration 沿 Z 轴的值,或者如果无法提供则为 null。
-
如果 acceleration 的 z 轴加速度 不为 null,则将其精度限制为不超过 0.1 m/s2。
-
-
令 platformAccelerationIncludingGravity 为 null。
-
否则,如果实现能够提供 包含重力的加速度
-
将 platformAccelerationIncludingGravity 设置为设备沿 X、Y 和 Z 轴的 线性加速度。
-
-
令 accelerationIncludingGravity 为 null。
-
如果 platformAccelerationIncludingGravity 不为 null
-
将 accelerationIncludingGravity 设置为在 window 的 Realm 中创建的 新
DeviceMotionEventAcceleration。 -
将 accelerationIncludingGravity 的 x 轴加速度 设置为 platformAccelerationIncludingGravity 沿 X 轴的值,或者如果无法提供则为 null。
-
如果 accelerationIncludingGravity 的 x 轴加速度 不为 null,则将其精度限制为不超过 0.1 m/s2。
-
将 accelerationIncludingGravity 的 y 轴加速度 设置为 platformAccelerationIncludingGravity 沿 Y 轴的值,或者如果无法提供则为 null。
-
如果 accelerationIncludingGravity 的 y 轴加速度 不为 null,则将其精度限制为不超过 0.1 m/s2。
-
将 accelerationIncludingGravity 的 z 轴加速度 设置为 platformAccelerationIncludingGravity 沿 Z 轴的值,或者如果无法提供则为 null。
-
如果 accelerationIncludingGravity 的 z 轴加速度 不为 null,则将其精度限制为不超过 0.1 m/s2。
-
-
令 platformRotationRate 为 null。
-
否则,如果实现能够提供 旋转速率
-
将 platformRotationRate 设置为设备绕 X、Y 和 Z 轴的 旋转速率。
-
-
令 rotationRate 为 null。
-
如果 platformRotationRate 不为 null
-
将 rotationRate 设置为在 window 的 Realm 中创建的 新
DeviceMotionEventRotationRate。 -
将 rotationRate 的 x 轴旋转速率 设置为 platformRotationRate 绕 X 轴的值,或者如果无法提供则为 null。
-
如果 rotationRate 的 x 轴旋转速率 不为 null,则将其精度限制为不超过 0.1 deg/s。
-
将 rotationRate 的 y 轴旋转速率 设置为 platformRotationRate 绕 Y 轴的值,或者如果无法提供则为 null。
-
如果 rotationRate 的 y 轴旋转速率 不为 null,则将其精度限制为不超过 0.1 deg/s。
-
将 rotationRate 的 z 轴旋转速率 设置为 platformRotationRate 绕 Z 轴的值,或者如果无法提供则为 null。
-
如果 rotationRate 的 z 轴旋转速率 不为 null,则将其精度限制为不超过 0.1 deg/s。
-
-
令 environment 为 window 的 相关设置对象。
-
并行 执行这些步骤
-
针对 « "accelerometer"(加速度计), "gyroscope"(陀螺仪) » 中的每个 permission
-
在 window 给定的 设备运动与方向任务源上 排队一个全局任务以执行以下步骤
-
触发一个事件,命名为 "devicemotion",目标为 window,使用
DeviceMotionEvent,并将acceleration属性初始化为 acceleration,accelerationIncludingGravity属性初始化为 accelerationIncludingGravity,rotationRate属性初始化为 rotationRate,以及interval属性初始化为 interval。
-
-
如果实现无法提供运动信息,则该事件触发时应将 acceleration、accelerationIncludingGravity 和 rotationRate 属性设置为 null。
7. 安全与隐私考量
本规范中定义的 API 可用于从硬件传感器获取信息,例如加速度计、陀螺仪和磁力计。提供的数据可能被视为敏感信息,并可能成为恶意网页攻击的目标。加速度计、陀螺仪和磁力计的校准可能会揭示特定传感器硬件的持久性细节 [SENSORID]。主要的攻击向量可归纳为以下几类:
-
监控用户输入 [TOUCH]
-
位置追踪 [INDOORPOS]
-
用户识别 [FINGERPRINT]
鉴于此,实现者可考虑使用视觉指示器来标识网页对传感器的使用。此外,本规范要求用户通过 requestPermission() API 调用给予用户代理明确许可,以提供设备运动和/或方向数据。
此外,为了最大限度地降低隐私风险、指纹识别和其他攻击的可能性,实现必须:
-
如前几节所述,限制属性值的精度。
此外,实施这些项目也可能对移动设备的电池寿命产生有益影响。
正在收集进一步的实现经验,以便为最大采样频率上限提供参考。
8. 无障碍考量
DeviceOrientation 事件为新型输入形式提供了契机,这可以为用户开启全新的交互方式。为了确保尽可能多的人能够与您构建的体验进行交互,请考虑以下事项:
-
提供替代的输入方式至关重要,这样无法完成所需手势的用户也有其他交互途径。例如患有灵巧度相关残疾的用户,或者使用视线追踪或头部追踪输入的用户。
-
对于游戏,请考虑支持游戏控制器、键盘或鼠标输入作为替代交互方法。
-
对于 Web 应用,请考虑提供 UI(例如按钮、菜单命令和/或键盘快捷键)来执行该功能。
-
-
用户必须能够撤销任何意外输入——这一点对于震颤患者尤为相关。
可能会出现两种用户需求,这些需求很可能由用户代理或底层操作系统来管理。然而,记住这些考量因素会有所帮助,因为它们代表了您的内容或应用可能被使用的方式。
-
用户能够禁用手势或基于运动的输入非常重要。Web 应用应提供一种适当的、无障碍的方式供用户提供此输入,例如按钮。
-
例如:虽然“摇晃以撤销”功能对某些人来说可以提供自然且贴心的交互,但对于有震颤的用户来说,它可能会构成障碍。这可以通过拒绝权限来管理,或者更有可能通过更改浏览器或操作系统设置,并配合 Web 应用提供的替代输入手段来管理。
-
-
能够锁定设备的方向也很重要——一个主要的使用场景是用户以非视觉方式与触摸设备(例如手机)交互。他们可能已经建立起关于元素在给定方向下位于屏幕何处的“肌肉记忆”,而布局的偏移会破坏他们的导航能力。同样,这很可能是在操作系统层面完成的。
9. 自动化
本规范可能会给测试作者带来挑战,因为此处定义的事件依赖于物理硬件的存在,而这些硬件的读数无法轻易控制。
为了应对这一挑战,本文档建立在 [WEBDRIVER2] 扩展命令以及 通用传感器 API § 9 自动化中制定的基础设施之上。之所以选择这种方案,而不是开发全新的独立基础设施,是因为两个规范之间存在显著重叠:不仅测试 [GENERIC-SENSOR] 规范存在类似的挑战,而且许多派生 API(例如 [GYROSCOPE])获取和提供的信息也相似。
本规范仅要求实现支持 [GENERIC-SENSOR] 规范的 通用传感器 API § 9 自动化部分,而不需要支持其接口和事件。
9.1. 设备方向自动化
deviceorientation 事件的自动化支持建立在代表加速度计、陀螺仪以及(可选的)磁力计的虚拟传感器之上。
用户代理从平台获取的方向数据来自加速度计、陀螺仪以及(可选的)磁力计。然而,与运动数据不同,这些底层读数必须转换为 § 3.1 设备方向中所述格式的欧拉角。此外,平台可能会向用户代理提供额外的 API,这些 API 已经执行了从原始加速度和旋转数据到欧拉角的转换。
因此,本规范没有要求实现(和自动化用户)通过使用不同测量单位的底层虚拟传感器提供方向读数,而是为相对数据和方向数据定义了额外的虚拟传感器类型,格式与本规范使用的格式一致。
9.1.1. 解析方向读数数据算法
Object parameters:-
令 alpha 为从 parameters 中调用获取属性方法并传入 "alpha" 的结果。
-
如果 alpha 不是
Number,或者其值为 NaN、+∞ 或 −∞,则返回undefined。 -
如果 alpha 不在 [0, 360) 范围内,则返回
undefined。 -
令 beta 为从 parameters 中调用获取属性方法并传入 "beta" 的结果。
-
如果 beta 不是
Number,或者其值为 NaN、+∞ 或 −∞,则返回undefined。 -
如果 beta 不在 [-180, 180) 范围内,则返回
undefined。 -
令 gamma 为从 parameters 中调用获取属性方法并传入 "gamma" 的结果。
-
如果 gamma 不是
Number,或者其值为 NaN、+∞ 或 −∞,则返回undefined。 -
如果 gamma 不在 [-90, 90) 范围内,则返回
undefined。 -
返回一个新的有序映射 «[ "alpha" → alpha, "beta" → beta, "gamma" → gamma ]»。
注意: 返回值是一个有序映射,以防止依赖于 [GENERIC-SENSOR] 规范中的传感器读数概念。对于上述算法而言,它们应该是可互换的。
9.1.2. "absolute-orientation"(绝对方向)虚拟传感器类型
按类型虚拟传感器元数据映射必须包含以下条目:
9.1.3. "relative-orientation"(相对方向)虚拟传感器类型
按类型虚拟传感器元数据映射必须包含以下条目:
9.2. 设备运动自动化
用户代理从平台获取的运动数据来自加速度计和陀螺仪。本规范定义了某些与 [ACCELEROMETER] 和 [GYROSCOPE] 规范共享的按类型虚拟传感器元数据条目。
加速度计虚拟传感器用于向平台提供含重力加速度数据。线性加速度虚拟传感器用于向平台提供线性加速度数据。陀螺仪虚拟传感器用于向平台提供旋转速率数据。
9.2.1. "accelerometer"(加速度计)虚拟传感器类型
按类型虚拟传感器元数据映射必须包含以下条目:
9.2.2. "linear-acceleration"(线性加速度)虚拟传感器类型
按类型虚拟传感器元数据映射必须包含以下条目:
9.2.3. "gyroscope"(陀螺仪)虚拟传感器类型
按类型虚拟传感器元数据映射必须包含以下条目:
A 示例
本节是非规范性的。A.1 计算指南针方位
本节是非规范性的。
以下示例旨在帮助 DeviceOrientation 事件的用户。
简介部分提供了一个示例,说明了当设备屏幕水平放置时,如何使用 DeviceOrientation 事件获取指南针方位。此示例展示了当用户将设备屏幕大致垂直地持于面前时,如何确定用户所面对的指南针方位。增强现实系统是此功能的一个应用场景。
更精确地说,我们希望确定一个与设备屏幕正交且指向屏幕背面的矢量的水平分量的指南针方位。
如果 v 表示旋转后的设备本体坐标系 xyz 中的该矢量,则 v 如下所示。
由于绕 z 轴旋转导致的 v 的变换可以用以下旋转矩阵表示。
由于绕 x 轴旋转导致的 v 的变换可以用以下旋转矩阵表示。
由于绕 y 轴旋转导致的 v 的变换可以用以下旋转矩阵表示。
如果 R 表示设备在地球坐标系 XYZ 中的完整旋转矩阵,并且由于初始本体坐标系与地球坐标系对齐,则 R 如下所示。
如果 v' 表示地球坐标系 XYZ 中的矢量 v,并且由于初始本体坐标系与地球坐标系对齐,则 v' 如下所示。
指南针方位 θ 由以下公式给出:
前提是 β 和 γ 不全为零。
上述指南针方位计算可以用 JavaScript 表示如下,以便在提供的参数已定义、非 null 且表示absolute(绝对)值时,返回正确的指南针方位。
var degtorad= Math. PI/ 180 ; // Degree-to-Radian conversion function compassHeading( alpha, beta, gamma) { var _x= beta? beta* degtorad: 0 ; // beta value var _y= gamma? gamma* degtorad: 0 ; // gamma value var _z= alpha? alpha* degtorad: 0 ; // alpha value var cX= Math. cos( _x); var cY= Math. cos( _y); var cZ= Math. cos( _z); var sX= Math. sin( _x); var sY= Math. sin( _y); var sZ= Math. sin( _z); // Calculate Vx and Vy components var Vx= - cZ* sY- sZ* sX* cY; var Vy= - sZ* sY+ cZ* sX* cY; // Calculate compass heading var compassHeading= Math. atan( Vx/ Vy); // Convert compass heading to use whole unit circle if ( Vy< 0 ) { compassHeading+= Math. PI; } else if ( Vx< 0 ) { compassHeading+= 2 * Math. PI; } return compassHeading* ( 180 / Math. PI); // Compass Heading (in degrees) }
作为一致性检查,如果我们设置 γ = 0,则
符合预期。
或者,如果我们设置 β = 90,则
符合预期。
A.2 其他设备方向表示法
本节是非规范性的。
使用 Tait-Bryan 角描述方向可能会有一些缺点,例如引入万向节死锁 [GIMBALLOCK]。根据预期的应用,将设备方向值转换为其他旋转表示法可能很有用。
第一种替代的方向表示法使用旋转矩阵。通过组合上述示例中提供的分量旋转矩阵,我们可以将设备本体坐标系的方向表示为一个组合旋转矩阵。
如果 R 表示设备在地球坐标系 XYZ 中的旋转矩阵,并且由于初始本体坐标系与地球坐标系对齐,则 R 如下所示。
absolute(绝对)值。var degtorad= Math. PI/ 180 ; // Degree-to-Radian conversion function getRotationMatrix( alpha, beta, gamma) { var _x= beta? beta* degtorad: 0 ; // beta value var _y= gamma? gamma* degtorad: 0 ; // gamma value var _z= alpha? alpha* degtorad: 0 ; // alpha value var cX= Math. cos( _x); var cY= Math. cos( _y); var cZ= Math. cos( _z); var sX= Math. sin( _x); var sY= Math. sin( _y); var sZ= Math. sin( _z); // // ZXY rotation matrix construction. // var m11= cZ* cY- sZ* sX* sY; var m12= - cX* sZ; var m13= cY* sZ* sX+ cZ* sY; var m21= cY* sZ+ cZ* sX* sY; var m22= cZ* cX; var m23= sZ* sY- cZ* cY* sX; var m31= - cX* sY; var m32= sX; var m33= cX* cY; return [ m11, m12, m13, m21, m22, m23, m31, m32, m33]; };
另一种设备方向数据的替代表示法是四元数。 [QUATERNIONS]
如果 q 表示设备在地球坐标系 XYZ 中的单位四元数,并且由于初始本体坐标系与地球坐标系对齐,则 q 如下所示。
absolute(绝对)值且这些参数不为 null。var degtorad= Math. PI/ 180 ; // Degree-to-Radian conversion function getQuaternion( alpha, beta, gamma) { var _x= beta? beta* degtorad: 0 ; // beta value var _y= gamma? gamma* degtorad: 0 ; // gamma value var _z= alpha? alpha* degtorad: 0 ; // alpha value var cX= Math. cos( _x/ 2 ); var cY= Math. cos( _y/ 2 ); var cZ= Math. cos( _z/ 2 ); var sX= Math. sin( _x/ 2 ); var sY= Math. sin( _y/ 2 ); var sZ= Math. sin( _z/ 2 ); // // ZXY quaternion construction. // var w= cX* cY* cZ- sX* sY* sZ; var x= sX* cY* cZ- cX* sY* sZ; var y= cX* sY* cZ+ sX* cY* sZ; var z= cX* cY* sZ+ sX* sY* cZ; return [ w, x, y, z]; }
我们可以使用拉格朗日四平方和定理来检查单位四元数是否已正确构造:
符合预期。
致谢
“设备方向和运动”规范最初于 2016 年 8 月以《设备方向事件规范》为题作为候选推荐标准发布,最初由地理定位工作组开发。该工作组于 2017 年解散后,该规范被暂时搁置。该文档于 2019 年由设备和传感器工作组重启,并进行了重大改进,包括在互操作性、测试自动化、隐私和编辑内容方面的提升(参见§ 10 变更部分)。
2024 年,设备和传感器工作组与Web 应用工作组展开合作,使其成为一项联合交付成果,并继续推动该规范的发展。最初的设计讨论并未保存在此 GitHub 仓库中,但可以通过地理定位工作组的邮件列表存档进行查阅。
W3C 感谢 Lars Erik Bolstad、Dean Jackson、Claes Nilsson、George Percivall、Doug Turner、Matt Womer 和 Chris Dumez 的贡献。
10. 变更
本节总结了重要的变更和值得注意的编辑改进,以指导审查。详情请参阅提交日志。自候选推荐标准 2016-08-18 以来的变更:
-
添加权限策略集成,取代了之前仅在与顶级框架同源的 iframe 上触发事件的要求。
-
向实现者添加关于捆绑权限请求的说明。
-
导出强大功能:加速度计、陀螺仪和磁力计。
-
添加 Permissions API 集成,开始要求使用 requestPermission()。
-
编辑:更规范地定义 API 部分,并增加更多 dfn。
-
编辑:重排“设备运动模型”部分中的加速度解释。
-
编辑:更新设备旋转和运动参考的解释。
-
编辑:使用更精确的事件处理术语,并更新其他术语。
-
编辑:参考 [SCREEN-ORIENTATION] 而不是方向改变事件。
-
编辑:重写“安全与隐私考量”中的要求。
-
将用例、要求和示例部分标记为非规范性。
-
移除 oncompassneedscalibration 事件。
-
更新对“由用户激活触发”的引用,现称为“瞬态激活”。
-
与 DOM 关于触发事件的措辞保持一致。
-
添加关于 DeviceMotionEvent 加速度属性的说明。
-
添加说明坐标系如何不同于 CSS 坐标系的说明。
-
要求精度不高于 0.1 度、0.1 度每秒、0.1 米每平方秒,以缓解被动指纹识别问题。
-
更新 IDL 中的构造函数定义以符合 Web IDL。
-
向接口添加显式的 [Exposed]。
-
更新 IDL 字典,采用新的字典默认设置。
-
注明 deviceorientationabsolute 事件及其 ondeviceorientationabsolute 事件处理程序 IDL 属性的实现经验有限。
-
向 DeviceOrientationEvent 和 DeviceMotionEvent 添加 requestPermission() API 静态操作。
-
向事件处理程序 ondeviceorientation、ondevicemotion 和 ondeviceorientationabsolute 添加 [SecureContext]。
-
将所有接口限制为仅在安全上下文中使用。
-
从 DeviceAcceleration 和 DeviceRotationRate 中移除 [NoInterfaceObject]。
-
使安全与隐私考量成为规范性内容。
-
在 IDL 块中添加 ondeviceorientationabsolute 事件处理程序属性(之前仅在正文中)。
-
从 DeviceMotionEventInit 的字典成员中移除 '?'。
-
使用 [Exposed=Window] 扩展属性。