# Vibration API

> 使用 navigator.vibrate() 提供简单触觉反馈，检测支持、取消模式，并处理用户激活、页面可见性与平台限制。

Vibration API 通过 `navigator.vibrate()` 提供简单触觉反馈，参数可以是一个振动时长，也可以是由振动与暂停时长交替组成的序列。

W3C 规范记录了 Chromium 系浏览器的实现、WebKit 的反对立场，以及 Firefox 129 移除实现；规范把该功能描述为有限可用，也没有提供判断振动硬件是否存在或启用的方法。

## 支持情况

W3C 规范记录了 Chromium 系浏览器的支持、WebKit 的反对立场，以及 Firefox 129 移除实现。即使该方法存在，API 也无法报告振动硬件是否存在或启用。

## 语法

```js
navigator.vibrate(duration);
navigator.vibrate([vibrate, pause, vibrate]);
```

该方法返回布尔值；普通 Web 文档不可见、缺少粘性用户激活或实现拒绝请求时，规范返回 `false`。返回 `true` 不能证明设备具有振动硬件。规范指出，与操作系统功能深度集成的可信或特权应用可以忽略可见性检查。

## 参数

`pattern` 是以毫秒计的无符号时长，或无符号时长序列。序列从振动开始，在振动与暂停之间交替。规范会在 10 项之后截断序列，并把每项上限设为 10,000 毫秒。

传入 `0`、空数组或全部项目均为零的数组，会取消正在执行的模式。

## 异常

`vibrate()` 没有定义 DOM 异常。对于普通 Web 文档，隐藏文档会返回 `false`；规范允许与操作系统功能深度集成的可信或特权应用忽略该可见性检查。新的已接受模式开始前，现有模式会被中止。顶层文档变为隐藏状态时，用户代理必须中止正在运行的振动算法。

:::caution
Mozilla 缺陷 1924685 记录了 Ubuntu 上的 Firefox 131 对 `window.navigator.vibrate(500)` 返回 `Uncaught TypeError: window.navigator.vibrate is not a function`。这与规范所记 Firefox 在版本 129 移除实现一致。
:::

## 示例

两组示例都把振动与可见反馈配对，因为 API 存在并不能保证设备会实际振动。

### 用短振动确认操作

从用户操作中调用该方法，使文档具有粘性激活。回退路径会更新可见状态，让操作结果不只依赖振动来确认。

```html
<label>草稿 <textarea id="draft"></textarea></label>
<button id="save" type="button">保存草稿</button>
<p id="status" role="status"></p>

<script>
const saveButton = document.querySelector("#save");
const status = document.querySelector("#status");

saveButton.addEventListener("click", () => {
  localStorage.setItem("draft", document.querySelector("#draft").value);
  status.textContent = "草稿已保存";

  if ("vibrate" in navigator) {
    navigator.vibrate(80);
  } else {
    status.dataset.haptics = "unavailable";
  }
});
</script>
```

文本更新是回退分支；即使 `vibrate()` 存在但设备没有振动，它仍会显示。

### 启动并取消振动模式

取消时不需要保存计时器；传入零即可请求 API 停止活动模式。

```html
<button id="start-alert" type="button">启动提醒</button>
<button id="stop-alert" type="button">停止提醒</button>
<p id="visual-alert" role="status" hidden>提醒已启用</p>

<script>
const start = document.querySelector("#start-alert");
const stop = document.querySelector("#stop-alert");
const visualAlert = document.querySelector("#visual-alert");

function showVisualAlert() {
  visualAlert.hidden = false;
}

function hideVisualAlert() {
  visualAlert.hidden = true;
}

start.addEventListener("click", () => {
  showVisualAlert();
  if (!("vibrate" in navigator)) {
    return;
  }

  navigator.vibrate([100, 50, 100]);
});

stop.addEventListener("click", () => {
  if ("vibrate" in navigator) navigator.vibrate(0);
  hideVisualAlert();
});
</script>
```

视觉提示提供不支持时的路径，停止操作会清除两种反馈。

## 另请参阅

- [用户激活](/zh/reference/capabilities/user-activation/)，了解粘性激活要求
- [Notifications API](/zh/reference/notifications/notifications-api/)，用于系统通知，与简单触觉反馈用途不同
- [Vibration API](https://www.w3.org/TR/vibration/)（w3.org）
- [Navigator: vibrate() method](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/vibrate)（developer.mozilla.org）