Copyright © 2025 World Wide Web Consortium. W3C® liability, trademark and permissive document license rules apply.
Gamepad 规范定义了一个表示 游戏手柄设备的低级接口。
本节描述此 文档在发布时的状态。当前 W3C 出版物列表以及本技术报告的最新修订版可在 W3C 标准和草案 索引中找到。
这是一项正在进行的工作。
本文档由 Web 应用工作 组 作为 工作草案使用 推荐标准轨道 发布。
作为工作草案发布并不 意味着获得 W3C 及其成员的认可。
这是一份草案文档,可能随时被其他 文档更新、替换或废弃。除作为正在进行的工作外, 不宜以其他方式引用本文档。
本文档由一个根据 W3C 专利 政策 运作的小组制作。 W3C 维护了一个 公开的专利 披露列表, 其中列出了与该小组交付成果相关的披露; 该页面还包括 披露专利的说明。实际 知晓某项专利且认为该专利包含 必要权利要求 的个人,必须按照 W3C 专利政策第 6 节 披露相关信息。
本文档受 2023年11月03日 W3C 流程文档管辖。
本节是非规范性的。
一些 用户代理 连接了 游戏手柄设备。这些设备 很适合用作游戏应用的输入,并适合用于“10 英尺”用户界面(演示、媒体查看器)。
目前,游戏手柄可用作输入的唯一方式是 模拟鼠标或键盘事件,然而这会丢失信息, 并且需要 用户代理 之外的额外软件来 完成模拟。
同时,原生应用能够通过系统 API 访问这些设备。
Gamepad API 通过指定 允许 Web 应用直接处理游戏手柄数据的接口, 为此问题提供了解决方案。
与为控制游戏而设计的外部设备交互, 如果以完全通用的方式处理, 可能会变得庞大且难以驾驭。在本规范中,我们明确选择缩小范围, 以提供一个有用的功能子集,该子集可以被广泛 实现并具有广泛用途。
具体而言,我们选择仅支持 支持游戏手柄所需的功能。支持游戏手柄需要两种输入类型: 按钮和轴。按钮和轴都以模拟值报告, 按钮范围为 [0 .. 1],轴范围为 [-1 .. 1]。
虽然主要目标是支持游戏手柄设备,但支持这 两种模拟输入类型也允许支持当前游戏系统中常见的 其他类似设备,包括操纵杆、方向盘、 踏板和加速度计。因此,“gamepad”这个名称是示例性的, 而不是试图作为本规范所涉及的整组设备的通用名称。
我们明确排除了对更复杂设备的支持,这些设备也可能 用于某些游戏场景,包括那些进行运动 感测、深度感测、视频分析、手势识别等的设备。
游戏手柄 是输入控件和输出 控件的集合。输入控件 具有一组可能随时间更新的 输入 值。输入控件包括 游戏手柄 的 按钮、扳机、操纵杆、摇杆和触摸表面。输出控件 是一种会改变 游戏手柄 行为的特性,用于向与 游戏手柄 交互的用户提供反馈。输出控件包括 游戏手柄 的触觉执行器。若 用户代理 能够读取 游戏手柄 的 输入控件 的当前状态,则该游戏手柄是 可用 的。一个 不 可用 的 游戏手柄 是 不可用 的。当 游戏手柄 是 可用 的时候, 该 游戏手柄 的 输入控件 和 输出控件 不能 改变。
用户代理 负责:
游戏手柄 具有一个 游戏手柄 标识符字符串,这是一个 人类可读的字符串,用于识别 游戏手柄 的品牌或样式。其内容由 用户代理 决定。
游戏手柄 可以具有一个 输入控件布局,它 描述 输入控件 在 游戏手柄 上的位置、方向和类型。用户代理 负责 识别 游戏手柄 何时 对应于标准布局,这意味着 该 游戏手柄 具有一个 输入 控件布局,使其能够与其他对应于 同一标准布局的 游戏手柄 互换使用。如果某布局的 输入控件 与标准布局中描述的 输入控件 具有大致相同的相对位置和方向,则 用户 代理 SHOULD 认为该布局 对应于标准布局。
用户代理 通常 不能直接检查某个 游戏手柄 的 输入控件布局,并且 MAY 使用启发式方法来决定 该布局。用户代理 SHOULD 在决定某个 游戏手柄 是否 对应于标准布局 时考虑设备标识符。如果系统为每个 输入控件 分配标签,并且 这些标签暗示某个特定布局,则 用户代理 SHOULD 认为该 游戏手柄 具有该布局。当存在 具有相同 输入控件 的 标准型号和无障碍型号时, 用户代理 SHOULD 认为该无障碍型号 具有与标准型号相同的 输入控件布局。
每个输入控件都有一个或多个关联的 输入值,这些值 是表示该控件当前状态的数值。 输入值 可随时更新。用户代理 负责 检测 输入值 何时已更新,并且 SHOULD 尽量减少更新与 读取更新后值之间的延迟。
读取某个 输入值 会返回其 逻辑值, 即 当前状态的未缩放数值表示。输入值 还 具有一个 逻辑 最小值 和一个 逻辑 最大值,它们定义边界内 逻辑值 的最小值和最大值。
输入值 可以具有一个关联的 HID usage identifier,这是一个 32 位值,用于识别 该输入值所表示的数据类型。HID usage 并不精确 描述 输入控件布局,但按照惯例,许多 布局类似的 游戏手柄 使用类似的 usages。用户代理 SHOULD 在决定 输入控件布局 时, 依赖围绕 HID usage identifiers 的惯例。
游戏手柄 可以具有 轴 输入。轴 是一个 输入值,表示控件相对于参考位置的当前位移。
游戏手柄 具有一个 轴 列表,它是一个 列表, 包含该 游戏手柄 的所有 轴 输入,顺序由 用户 代理 决定。
输入控件 可以被设计为在用户停止与 输入控件 交互时,自动将 轴 返回到中心位置。如果是这样,则该 轴 具有一个 首选轴 状态。具有 首选轴状态 的 轴 还可以 具有一个额外的 输入值,即 中心 位置 值,它是 轴 处于 中心位置时的 逻辑值。
游戏手柄 可以具有 触摸表面。触摸表面 是一种输入控件,提供表示接触点的 2D 位置数据。游戏手柄 具有一个 触摸 表面列表, 它是一个 列表,包含该 游戏手柄 的 触摸表面。该列表按如下方式排序:越靠近 游戏手柄 左侧的 触摸表面 越靠近 列表开头。
触摸表面 具有一个 活跃 触摸点列表 输入值,即一个包含零个或多个 触摸点 的 列表,表示传感器当前检测到的 接触点。触摸 点 表示单一时间点的单个接触点。触摸点 具有 触摸 x 坐标 和 触摸 y 坐标,表示其在 触摸表面 坐标系中的位置。如果某个 触摸表面 位于 游戏手柄 的顶部、底部、前侧或后侧,则 触摸 x 坐标 沿左右轴测量, 否则沿上下轴测量。触摸 y 坐标 沿垂直轴测量。
如果 触摸表面 位于 游戏手柄 的左侧或右侧, 则其两个维度都不会与水平轴对齐。
触摸表面 可以具有表面尺寸 输入值。表面 宽度 和 表面 高度 输入值 是 触摸表面 的尺寸,单位与 触摸 x 坐标 和 触摸 y 坐标 相同。触摸表面 要么同时具有两个尺寸值,要么两个都没有。
一个 触摸点 可以是新的接触点,也可以是
较早接触的延续。一个 触摸点 是 现有活跃
触摸点的一部分,如果 用户代理
识别出它是由较早的
GamepadTouch 表示的
触摸点 的延续。对于一个 触摸点,如果它是 现有
活跃触摸点的一部分,则其 活跃
触摸点 id 是较早的 GamepadTouch 的
touchId。
游戏手柄 可以具有 触觉 执行器。触觉 执行器 是一种输出控件,能够以用户可以感受到的方式移动 游戏手柄。 触觉执行器 可用于生成 触觉效果,向 用户提供反馈。来自多个执行器的振动会组合起来生成 更复杂的效果。用户 代理 负责 命令 触觉执行器 在 可用 的 游戏手柄 上播放和停止 触觉效果。
游戏手柄 可以具有一个 振动 执行器,它是一个 触觉执行器,能够播放 触觉效果 以振动 整个 游戏手柄。
触觉执行器 具有一个 列表,其中包含一个或多个
GamepadHapticEffectType
值,即 受支持的
效果
类型;当 游戏手柄 是 可用 时,
该列表不能改变。
此接口定义单个游戏手柄设备。
WebIDL[Exposed=Window]
interface Gamepad {
readonly attribute DOMString id;
readonly attribute long index;
readonly attribute boolean connected;
readonly attribute DOMHighResTimeStamp timestamp;
readonly attribute GamepadMappingType mapping;
readonly attribute FrozenArray<double> axes;
readonly attribute FrozenArray<GamepadButton> buttons;
readonly attribute FrozenArray<GamepadTouch> touches;
[SameObject] readonly attribute GamepadHapticActuator vibrationActuator;
};
用于与系统通信的算法通常会异步完成, 在 gamepad task source 上排队工作。
Gamepad 的实例使用下表中描述的内部槽创建:
| 内部槽 | 初始值 | 描述(非规范性) |
|---|---|---|
| [[connected]] |
false
|
指示设备已连接到系统的标志 |
| [[timestamp]] | undefined |
此 Gamepad 的数据上次更新的时间
|
| [[axes]] | 一个空的 sequence |
一个由 double 值组成的
sequence,
表示此设备暴露的轴的当前状态
|
| [[buttons]] | 一个空的 sequence |
一个由 GamepadButton 对象组成的
sequence,
表示此设备暴露的按钮的当前状态
|
| [[exposed]] |
false
|
指示 Gamepad 对象已被
暴露给
脚本的标志
|
| [[axisMapping]] | 一个空的 有序 映射 |
从未映射的轴索引到
axes 数组中某个索引的映射
|
| [[axisMinimums]] | 一个空的 列表 | 一个 列表,包含每个轴的 最小逻辑值 |
| [[axisMaximums]] | 一个空的 列表 | 一个 列表,包含每个轴的 最大逻辑值 |
| [[buttonMapping]] | 一个空的 有序 映射 |
从未映射的按钮索引到
buttons 数组中某个索引的映射
|
| [[buttonMinimums]] | 一个空的 列表 | 一个 列表,包含每个按钮的 最小逻辑值。 |
| [[buttonMaximums]] | 一个空的 列表 | 一个 列表,包含每个按钮的 最大逻辑值 |
| [[touches]] | 一个空的 列表 | 保存用户生成的触摸列表(如果有)。如果游戏手柄 不支持触摸表面,则该列表将保持为空。 |
| [[nextTouchId]] | 0 |
用于下一个传入触摸的
touchId 值。
|
| [[vibrationActuator]] | undefined |
一个 GamepadHapticActuator 对象,
能够生成振动整个游戏手柄的触觉
效果
|
id 属性
游戏手柄的标识字符串。此字符串标识 已连接游戏手柄设备的品牌或样式。
id 字符串的确切格式未指定。
RECOMMENDED 用户代理 选择一个
能识别产品但不会唯一识别设备的字符串。例如,
USB 游戏手柄可以通过其 idVendor 和
idProduct 值进行识别。序列号或
Bluetooth 设备地址等唯一标识符 MUST NOT 包含在
id 字符串中。
index 属性
Navigator
中的索引。当多个游戏手柄
连接到 用户
代理 时,索引 MUST 按
先到先服务的原则分配,从零开始。如果某个游戏手柄
断开连接,先前分配的索引 MUST NOT 重新分配给
仍保持连接的游戏手柄。但是,如果某个游戏手柄
断开连接,随后同一个或不同的游戏手柄
再次连接,则先前使用过的最低索引 MUST 被重用。
connected
属性
指示此对象所表示的物理设备是否
仍连接到系统。当游戏手柄变为不可用时,
无论是物理断开连接、关机还是以其他方式
无法使用,connected 属性 MUST
被设置为
false。
connected getter 步骤为:
[[connected]]。
timestamp
属性
timestamp 允许作者确定
此游戏手柄的 axes 或 buttons 属性上次更新的
时间。每当系统从设备 接收到新的按钮或轴输入
值 时,该值 MUST 被设置为 当前高分辨率
时间。如果尚未从硬件接收到数据,则
timestamp MUST 是
Gamepad 首次可供脚本使用时的
当前高分辨率
时间。
timestamp getter 步骤为:
[[timestamp]]。
mapping
属性
此设备正在使用的映射。如果 用户代理 知道
设备的布局,则它 SHOULD 通过将
mapping 设置为对应的
GamepadMappingType
值,来指示正在使用某个映射。
要为游戏手柄设备 选择映射,运行以下步骤:
standard"。
"。
axes 属性
游戏手柄所有轴的值数组。所有轴值 MUST 线性归一化到范围 [-1 .. 1]。如果控制器 垂直于地面且方向摇杆指向上方, -1 SHOULD 对应于“forward”或“left”,而 1 SHOULD 对应于“backward”或“right”。来自 2D 输入设备的轴 SHOULD 在 axes 数组中彼此相邻出现,先 X 后 Y。RECOMMENDED 轴按重要性递减的顺序出现, 使元素 0 和 1 通常表示方向摇杆的 X 和 Y 轴。同一对象 MUST 被返回, 直到 用户代理 需要返回不同的值(或 不同顺序的值)。
axes getter 步骤为:
buttons
属性
游戏手柄所有按钮的按钮状态数组。RECOMMENDED 按钮按重要性递减的顺序出现,使 主按钮、次按钮、第三按钮等 作为元素 0、1、2、... 出现在 buttons 数组中。同一 对象 MUST 被返回,直到 用户代理 需要返回 不同的值(或不同顺序的值)。
buttons getter 步骤为:
[[buttons]]。
touches
属性
一个由所有触摸表面生成的 GamepadTouch 对象组成的
列表。
touches getter 步骤为:
[[touches]]。
vibrationActuator 属性
一个表示设备主要振动执行器的
GamepadHapticActuator 对象。
vibrationActuator getter 步骤
为:
当系统 接收到新的按钮或轴输入值 时, 运行以下步骤:
Gamepad
对象。
要为 gamepad 更新 游戏手柄状态,运行 以下步骤:
[[timestamp]] 设置为 now。
Navigator
对象。
[[hasGamepadGesture]] 为
false,并且
gamepad 包含游戏手柄用户手势:
[[hasGamepadGesture]] 设置为
true。
[[gamepads]] 中的每个
connectedGamepad 执行以下操作:
null:
[[exposed]] 设置为
true。
[[timestamp]] 设置为
now。
Document;否则为
null。
null 且为
完全
活跃,则在 gamepad task source 上
排队
一个全局任务,以在
gamepad 的 相关
全局对象 上,使用 GamepadEvent 触发一个事件,
名为
gamepadconnected,
并将其
gamepad
属性初始化为
connectedGamepad。
要为 gamepad 映射并 归一化轴,运行 以下步骤:
unsigned long 值组成的
列表,
表示由 gamepad 所代表设备的每个轴
输入的最新逻辑轴输入值。
[[axisMapping]][rawAxisIndex]。
[[axisMinimums]][rawAxisIndex]。
[[axisMaximums]][rawAxisIndex]。
[[axes]][axisIndex] 设置为
normalizedValue。
要为 gamepad 映射 并归一化按钮,运行 以下步骤:
unsigned long 值组成的
列表,
表示由 gamepad 所代表设备的每个
按钮输入的最新逻辑按钮输入值。
[[buttonMapping]][rawButtonIndex]。
[[buttonMinimums]][rawButtonIndex]。
[[buttonMaximums]][rawButtonIndex]。
[[buttons]][mappedIndex]。
[[value]] 设置为
normalizedValue。
如果该按钮具有数字开关来指示纯按下
或释放状态,则当按钮被按下时,将 button.[[pressed]]
设置为 true;如果未被按下,则设置为 false。
否则,如果该值高于 按钮按下阈值,
则将 button.[[pressed]] 设置为
true;如果不高于该阈值,则设置为 false。
如果该按钮能够检测触摸,则当该按钮当前正被触摸时,将
button.[[touched]] 设置为 true。
否则,将 button.[[touched]] 设置为
button.[[pressed]]。
要为 gamepad 记录 触摸,运行以下 步骤:
Gamepad.[[touches]] 为空。
surfaceDimensions
设置为一个 DOMRectReadOnly,
其 width
和
height
初始化为触摸表面上的最大 X 和 Y
维度,单位为设备单位。
GamepadTouch 对象。
surfaceId 设置为 surfaceId。
touchId 设置为该
活跃触摸点的
touchId。
touchId 设置为
gamepad.[[nextTouchId]],并
递增
gamepad.[[nextTouchId]]。
如果 Gamepad 有多个触摸表面,则触摸 id 在各表面之间是唯一的。
position 设置为一个
新的
DOMPointReadOnly,
其中 x
初始化
为相对于设备触摸表面的设备 X 坐标,
并归一化到 [-1 .. 1],其中 -1 是最左
坐标,1 是最右坐标;并且
y
初始化为设备触摸
表面的坐标,并归一化到 [-1 .. 1],其中 -1 是最上
坐标,1 是最下坐标。
x = (2.0 * touchData.x / surfaceDimensions.width) -
1
y = (2.0 * touchData.y / surfaceDimensions.height) - 1
[[touches]]。
表示已连接游戏手柄设备的 新
Gamepad
通过执行以下步骤构造:
Gamepad 实例:
id 属性初始化为该游戏手柄的
标识字符串。
index 属性初始化为
为 gamepad 选择未使用的
游戏手柄索引 的结果。
mapping 属性初始化为
为游戏手柄设备 选择映射 的
结果。
[[connected]] 设置为 true。
[[timestamp]] 设置为给定
gamepad 的 相关
全局对象 的 当前高
分辨率时间。
[[axes]]
设置为
为 gamepad 初始化轴 的结果。
[[buttons]] 设置为
为 gamepad 初始化按钮 的结果。
[[vibrationActuator]] 设置为
为 gamepad 构造
GamepadHapticActuator 的结果。
要为 gamepad 选择未使用的 游戏手柄索引,运行以下步骤:
Navigator
对象。
[[gamepads]] 的 大小 − 1。
[[gamepads]][gamepadIndex] 为
null,则返回 gamepadIndex。
null 追加 到
navigator.[[gamepads]]。
[[gamepads]] 的 大小 − 1。
要为 gamepad 初始化轴,运行以下步骤:
[[axisMinimums]] 设置为一个由
unsigned long 值组成的
列表,其 大小 等于 inputCount,
包含每个轴输入的最小逻辑值。
[[axisMaximums]] 设置为一个由
unsigned long 值组成的
列表,其 大小 等于 inputCount,
包含每个轴输入的最大逻辑值。
否则:
[[axisMapping]][rawInputIndex] 设置为
canonicalIndex。
否则,将 rawInputIndex 追加 到 unmappedInputList。
[[axisMapping]][rawInputIndex] 设置为
axisIndex。
要为 gamepad 初始化按钮,运行以下步骤:
[[buttonMinimums]] 设置为一个由
unsigned long 值组成的
列表,
其 大小 等于 inputCount,
包含每个按钮输入的最小逻辑值。
[[buttonMaximums]] 设置为一个由
unsigned long 值组成的
列表,
其 大小 等于 inputCount,
包含每个按钮输入的最大逻辑值。
否则:
[[buttonMapping]][rawInputIndex]
设置为 canonicalIndex。
否则,将 rawInputIndex 追加 到 unmappedInputList。
[[buttonMapping]][rawInputIndex]
设置为 buttonIndex。
GamepadButton 追加 到
buttons。
此接口定义游戏手柄触摸表面上的一次触摸,该触摸表面
支持此类输入。该对象由一个触摸
touchId 组成,它唯一标识触摸
点,从输入介质(例如手指、触控笔等)接触
触摸设备时起,直到输入介质不再
接触触摸设备时为止。
WebIDLdictionary GamepadTouch {
unsigned long touchId;
octet surfaceId;
DOMPointReadOnly position;
DOMRectReadOnly? surfaceDimensions;
};
touchId 属性
surfaceId 属性
position 属性
DOMPointReadOnly,保存
该触摸的 x、
y 坐标。
z 和 w 值
目前未使用。每个坐标的范围都归一化到
[-1 .. 1]。沿 x 轴,-1 表示最左坐标,
1 表示最右坐标。沿 y 轴,-1
表示最上坐标,1 表示最下
坐标。
surfaceDimensions 属性
DOMRectReadOnly,
以触摸表面的
width
和 height
初始化,单位为整数单位。
如果不可用,则为 null。
此枚举定义 Gamepad 的已知映射集合。
WebIDLenum GamepadMappingType {
"",
"standard",
"xr-standard",
};
""
standard"
xr-standard"
getGamepads() 返回的
Gamepad 对象 MUST NOT 报告
"xr-standard" 的
mapping。
GamepadHapticActuator
对应于一组电机或
其他执行器的配置,这些执行器能够施加力以用于触觉
反馈。
WebIDL[Exposed=Window]
interface GamepadHapticActuator {
[SameObject] readonly attribute FrozenArray<GamepadHapticEffectType> effects;
Promise<GamepadHapticsResult> playEffect(
GamepadHapticEffectType type,
optional GamepadEffectParameters params = {}
);
Promise<GamepadHapticsResult> reset();
};
GamepadHapticActuator 的实例
使用下表中描述的内部
槽创建:
| 内部槽 | 初始值 | 描述 |
|---|---|---|
| [[effects]] |
一个由 GamepadHapticEffectType 组成的空 列表。
|
表示该执行器支持的效果。 |
| [[playingEffectPromise]] |
null
|
用于播放某个
效果的 Promise,如果没有效果正在
播放,则为 null。
|
effects 属性
由 GamepadHapticEffectType 值组成的数组,
表示
执行器支持的所有触觉效果类型。此
属性列出执行器支持的 GamepadHapticEffectType 值,除非
用户代理 不支持
播放该类型的效果。
effects getter 步骤为:
[[effects]]。
playEffect() 方法
playEffect()
方法步骤,在使用
GamepadHapticEffectType type 和
GamepadEffectParameters params 调用时,为:
TypeError 拒绝的
promise。
Document。
null,或 document 不是 完全
活跃,或 document 的 可见性
状态 为
"hidden",则返回一个以
"InvalidStateError"
DOMException 拒绝的
promise。
[[playingEffectPromise]]
不为 null:
[[playingEffectPromise]]。
[[playingEffectPromise]]
设置为
null。
preempted" 兑现
effectPromise。
GamepadHapticActuator 不能 播放类型为 type 的效果,则返回一个以
NotSupportedError
为理由
拒绝的
promise。
[[playingEffectPromise]] 为 一个新的 promise。
[[playingEffectPromise]] 不为
null,则在 gamepad task source
上,使用 this 的 相关
全局对象 排队
一个全局任务 以运行
以下步骤:
[[playingEffectPromise]]
为 null,则中止这些步骤。
complete"
兑现
this.[[playingEffectPromise]]。
[[playingEffectPromise]]
设置为 null。
[[playingEffectPromise]]。
reset() 方法
reset() 方法
步骤为:
Document。
null,或 document 不是 完全
活跃,或 document 的 可见性
状态 为
"hidden",则返回一个以
"InvalidStateError"
DOMException 拒绝的
promise。
[[playingEffectPromise]]
不为 null,则并行执行以下步骤:
[[playingEffectPromise]]。
[[playingEffectPromise]]
仍然相同,则将
this.[[playingEffectPromise]]
设置为 null。
preempted"
兑现
effectPromise。
complete"
兑现 resetResultPromise
如果 type
可以在 [[effects]] 列表 中找到,则
GamepadHapticActuator 可以
播放类型为
type 的效果。
要检查具有 GamepadHapticEffectType
type 和 GamepadEffectParameters
params 的效果是否描述了一个 有效效果,
运行以下步骤:
GamepadHapticEffectType
type 的值,进行 switch:
dual-rumble"
false。
trigger-rumble"
false。
true
要在执行器上 发出
触觉效果,用户代理
MUST 向设备发送命令,以渲染类型为
type 的效果,并尝试让其使用提供的
params。当 params.startDelay 不为
0.0 时,用户代理 SHOULD 使用
提供的 playEffectTimestamp 以获得更精确的
播放时序。用户
代理 MAY 修改效果以提高
兼容性。例如,原本用于 rumble 电机的效果
可以被转换为基于波形的效果,用于支持
波形触觉但缺少 rumble 电机的设备。
要在执行器上 停止触觉 效果,用户代理 MUST 向设备发送命令,以中止当前正在 播放的任何效果。如果触觉效果被中断,则执行器 SHOULD 尽快返回到静止状态。
当 document 的 可见性状态
变为
"hidden" 时,对每个 GamepadHapticActuator
actuator 运行这些步骤:
[[playingEffectPromise]]
为 null,则中止这些步骤。
[[playingEffectPromise]] 为
null,则中止这些步骤。
preempted"
兑现
actuator.[[playingEffectPromise]]。
[[playingEffectPromise]] 设置为
null。
表示
Gamepad 的主振动执行器的 新
gamepadHapticActuator 通过
执行以下步骤构造:
GamepadHapticActuator 实例。
supportedEffectsList 为一个空的 列表。
GamepadHapticEffectType 的每个枚举值 type,如果 用户代理 可以向该执行器
发送命令以启动该类型的效果,则将 type 追加到
supportedEffectsList。
[[effects]]
设置为 supportedEffectsList。
WebIDLenum GamepadHapticsResult {
"complete",
"preempted"
};
complete
触觉效果已完成播放。
preempted
当前效果已被另一个效果停止或替换(即“preempted”)。
效果类型定义效果参数如何由 执行器解释。
WebIDLenum GamepadHapticEffectType {
"dual-rumble",
"trigger-rumble"
};
dual-rumble" 效果类型
"dual-rumble" 描述了一种
触觉
配置,在标准游戏手柄的每个握柄中都有一个偏心旋转质量(ERM)振动电机。
在此配置中,任一电机都能够振动整个游戏手柄。每个电机产生的
振动效果并不相同,因此二者的效果
可以组合起来创建更复杂的触觉效果。
"dual-rumble" 效果是
一种固定时长、恒定强度的振动效果,适用于此类型的
执行器。"dual-rumble"
效果由 startDelay、
duration、
strongMagnitude 和
weakMagnitude 定义,
这些都不是
必需的,因为它们默认值为 0。
strongMagnitude 和
weakMagnitude 设置
低频和高频振动的强度级别,归一化到
范围 [0 .. 1],默认值为 0。
给定 GamepadEffectParameters params,
一个 有效的 dual-rumble 效果 必须具有一个 有效的 duration、一个 有效的 startDelay,并且
strongMagnitude 和
weakMagnitude 都必须位于
范围 [0
.. 1] 内。
trigger-rumble" 效果类型
"trigger-rumble"
描述了一种触觉
配置,在 Standard Gamepad 的每个底部前侧
按钮(具有 规范索引 6 和 7 的按钮)中都有一个振动电机,并且还包含用于
"dual-rumble" 的两个
握柄电机。这些按钮最
常见的形式是弹簧加载的扳机。在此
配置中,任一电机都能够在按钮表面提供局部
触觉反馈。
"trigger-rumble"
效果是
一种固定时长、恒定强度的振动效果,适用于此类型的
执行器。"trigger-rumble"
效果由 startDelay、
duration、
strongMagnitude、
weakMagnitude、
leftTrigger 和
rightTrigger 定义,
这些都不是
必需的,因为它们默认值为 0。
startDelay、
duration、
strongMagnitude、
weakMagnitude 与
"dual-rumble" 具有相同定义。
leftTrigger 和
rightTrigger
分别设置
左、右底部前侧按钮振动的强度级别,
归一化到范围 [0 .. 1],默认值为 0。
给定 GamepadEffectParameters params,
一个 有效的 trigger-rumble 效果 必须具有一个 有效的 duration、一个 有效的 startDelay,并且
strongMagnitude、
weakMagnitude、
leftTrigger 和
rightTrigger 必须位于
范围 [0 ..
1] 内。
GamepadEffectParameters 字典包含用于触觉效果的参数
键。每个键的含义由
触觉效果定义,并且某些键可能未被使用。
为缓解不需要的长时间运行效果,用户代理 MAY 将 有效效果 的总效果持续时间限制为某个最大 时长。RECOMMENDED 用户代理 使用最大 5 秒。
WebIDLdictionary GamepadEffectParameters {
unsigned long long duration = 0;
unsigned long long startDelay = 0;
double strongMagnitude = 0.0;
double weakMagnitude = 0.0;
double leftTrigger = 0.0;
double rightTrigger = 0.0;
};
duration
成员
duration 设置
振动效果的
持续时间,单位为毫秒。
startDelay
成员
startDelay 设置在调用
playEffect() 之后到
振动开始之前的延迟
持续时间,单位为毫秒。在延迟间隔期间,
执行器 SHOULD NOT 振动。
strongMagnitude 成员
dual-rumble" 或
"trigger-rumble" 效果中
低频 rumble 的振动强度。
weakMagnitude 成员
dual-rumble" 或
"trigger-rumble" 效果中
高频 rumble 的振动强度。
leftTrigger 成员
trigger-rumble"
效果中底部左前按钮(规范
索引 6)的 rumble 振动强度。
rightTrigger 成员
trigger-rumble" 效果中
底部右前按钮
(规范索引 7)的 rumble 振动强度。
WebIDL[Exposed=Window]
interface GamepadEvent: Event {
constructor(DOMString type, GamepadEventInit eventInitDict);
[SameObject] readonly attribute Gamepad gamepad;
};
gamepad 属性
gamepad 属性提供对此事件的
关联游戏手柄数据的访问。
WebIDLdictionary GamepadEventInit : EventInit {
required Gamepad gamepad;
};
gamepad 成员
Gamepad。
每个设备制造商都会创建许多不同的产品,并且每种产品都有 独特的按钮和轴样式与布局。本意是 用户代理 尽可能支持尽可能多的 这些设备。
此外,还有由游戏主机普及起来的事实上的标准布局。 当 用户代理 识别出 已连接设备时,RECOMMENDED 在可能的情况下将其重映射到 规范顺序。未被识别的设备 仍应以其原始形式暴露。
目前有一个规范布局,即 Standard
Gamepad。重映射时,axes 和
buttons 中的索引应尽可能对应于
下图中的
物理位置。此外,
mapping SHOULD 被设置为
"standard"。
Standard Gamepad 按钮布局为:左侧一组四个 按钮、右侧一组四个按钮、中间一组三个 按钮,以及游戏手柄左侧和右侧的一对朝前按钮。 "Standard Gamepad" 的四个轴与 一对模拟摇杆相关联,一个在左侧,一个在右侧。下 表描述了按钮/轴及其物理 位置。
如果某个轴输入 报告的是拇指摇杆轴的输入值,该拇指摇杆 位于与对应的 Standard Gamepad 拇指摇杆大致相同的位置,并且轴的方向 (上下或左右)与 Standard Gamepad 轴的方向匹配,则该轴输入 表示一个 Standard Gamepad 轴。如果有多个轴表示同一个 Standard Gamepad 轴,则 用户代理 SHOULD 选择 一个作为 Standard Gamepad 轴,并为 另一个轴分配不同的索引。
如果某个按钮输入 报告的是按钮或扳机的输入值,并且该按钮或 扳机位于与对应的 Standard Gamepad 按钮大致相同的位置,则该按钮输入 表示一个 Standard Gamepad 按钮。
如果某个轴或按钮输入表示一个 Standard Gamepad 轴或 按钮,则其 规范索引 是对应的 Standard Gamepad 轴或按钮的索引。
| 类型 | 索引 | 位置 |
|---|---|---|
| 按钮 | 0 | 右侧按钮组中的底部按钮 |
| 1 | 右侧按钮组中的右侧按钮 | |
| 2 | 右侧按钮组中的左侧按钮 | |
| 3 | 右侧按钮组中的顶部按钮 | |
| 4 | 顶部左前按钮 | |
| 5 | 顶部右前按钮 | |
| 6 | 底部左前按钮 | |
| 7 | 底部右前按钮 | |
| 8 | 中间按钮组中的左侧按钮 | |
| 9 | 中间按钮组中的右侧按钮 | |
| 10 | 左摇杆按下按钮 | |
| 11 | 右摇杆按下按钮 | |
| 12 | 左侧按钮组中的顶部按钮 | |
| 13 | 左侧按钮组中的底部按钮 | |
| 14 | 左侧按钮组中的左侧按钮 | |
| 15 | 左侧按钮组中的右侧按钮 | |
| 16 | 中间按钮组中的中央按钮 | |
| 轴 | 0 | 左摇杆的水平轴(负值向左/正值向右) |
| 1 | 左摇杆的垂直轴(负值向上/正值向下) | |
| 2 | 右摇杆的水平轴(负值向左/正值向右) | |
| 3 | 右摇杆的垂直轴(负值向上/正值向下) |
检查 Gamepad 对象的能力可被用作
主动指纹识别的一种手段。用户代理 MAY 更改
通过 API 暴露的
设备信息,以减少
指纹识别表面。例如,某个实现可以要求
Gamepad 对象恰好具有
Standard Gamepad 布局中定义的按钮和轴数量,
即使已连接设备上存在更多或更少的
输入。
[FINGERPRINTING-GUIDANCE]
本节是非规范性的。
下面的示例演示了对游戏手柄的典型访问。请注意其
与
requestAnimationFrame()
方法的关系。
function runAnimation() {
window.requestAnimationFrame(runAnimation);
for (const pad of navigator.getGamepads()) {
// todo;显示 pad.axes 和 pad.buttons 的简单演示
console.log(pad);
}
}
window.requestAnimationFrame(runAnimation);
requestAnimationFrame() 协调
交互式应用通常会使用
requestAnimationFrame()
方法来驱动
动画,并希望将动画与用户游戏手柄
输入相协调。因此,游戏手柄数据应尽可能接近
动画回调执行前立即进行轮询,
并以与动画匹配的频率进行轮询。也就是说,如果
动画回调以 60Hz 运行,则游戏手柄输入
也应以该速率采样。
当游戏手柄在系统上变为可用时,运行以下 步骤:
Document;否则为 null。
null 且不 允许
使用
"gamepad" 权限,则中止这些步骤。
Gamepad。
Navigator
对象。
[[gamepads]][gamepad.index]
设置为 gamepad。
[[hasGamepadGesture]] 为
true:
[[exposed]] 设置为 true。
null 且为 完全
活跃,则在
gamepad 的 相关
全局对象 上,使用 GamepadEvent 触发一个事件,名为 gamepadconnected,
并将其 gamepad 属性
初始化为
gamepad。
实现本规范的用户代理
必须提供一个新的 DOM
事件,名为 gamepadconnected。相应事件
MUST 为
GamepadEvent 类型,并且 MUST 在
Window
对象上触发。
用户代理 MUST 分发此事件类型,以指示用户已
连接游戏手柄。如果页面加载时游戏手柄
已经连接,则当
用户按下按钮或移动轴时,gamepadconnected 事件 SHOULD 被分发。
当游戏手柄在系统上变为不可用时,运行以下 步骤:
Gamepad。
[[connected]] 设置为 false。
Document;否则为 null。
[[exposed]] 为 true 且 document
不为 null 且为 完全
活跃,则在 gamepad 的 相关
全局对象 上,使用 GamepadEvent 触发一个事件,名为 gamepaddisconnected,
并将其
gamepad 属性初始化为
gamepad。
Navigator
对象。
[[gamepads]][gamepad.index]
设置为 null。
[[gamepads]] 不为空 且
navigator.[[gamepads]] 的最后一个 项 为 null 时,
移除
navigator.[[gamepads]] 的最后一个 项。
实现本规范的用户代理
必须提供一个新的 DOM
事件,名为 gamepaddisconnected。相应事件
MUST 为
GamepadEvent 类型,并且 MUST 在
Window
对象上触发。
当游戏手柄从 用户代理 断开连接时,如果 用户代理 先前已向某个
Window 为该
游戏手柄分发过 gamepadconnected 事件,则
gamepaddisconnected 事件 MUST 被
分发到同一个 Window。
需要更多讨论,以决定是否包含或排除轴和
按钮变化事件,以及是否将它们更合并在一起
("gamepadchanged"?)、略微分开("gamepadaxischanged"?),或
按单个轴和按钮分别处理。
本规范扩展 HTML 中的 WindowEventHandlers
接口 mixin,
以添加 事件处理器
IDL 属性,从而便于
事件处理器注册。
WebIDLpartial interface mixin WindowEventHandlers {
attribute EventHandler ongamepadconnected;
attribute EventHandler ongamepaddisconnected;
};
本规范定义了一个由策略控制的特性,其标识字符串为 "gamepad"。其 默认 允许列表 是 *。
一个 document 的 permissions
policy 决定该文档中的
任何内容是否被允许访问
getGamepads()。如果
在任何文档中被禁用,则该文档中的任何内容
都不 允许
使用
getGamepads(),并且
gamepadconnected 和
gamepaddisconnected
事件也不会触发。
除标记为非规范性的章节外,本规范中的所有创作指南、图表、示例和注释均为非规范性内容。本规范中的其他所有内容均为规范性内容。
本文档中的关键词 MAY、MUST、MUST NOT、RECOMMENDED、SHOULD 和 SHOULD NOT 应按 BCP 14 [RFC2119] [RFC8174] 中的描述进行解释,且仅当它们全部以 大写形式出现时才如此,如此处所示。
本节是非规范性的。
以下人员为本文档的开发做出了贡献。
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in: