navigator.vibrate仅在chrome for android、firefox for android、samsung internet等现代安卓浏览器支持,ios safari完全禁用且navigator.vibrate为undefined。

navigator.vibrate 在哪些浏览器里能用
只有支持 Web API 的现代移动浏览器才真正实现 navigator.vibrate,比如 Chrome for Android、Firefox for Android、Samsung Internet;iOS Safari 完全不支持——不是“暂时没加”,而是苹果明确禁用该 API,连 navigator.vibrate 这个属性在 iOS 上都为 undefined。
所以第一步永远是检测:
if ('vibrate' in navigator && typeof navigator.vibrate === 'function') {
navigator.vibrate(50); // 可行
} else {
// 降级:改用 CSS 动画或声音提示
}
别跳过这个判断,否则在 iOS 或旧版安卓上会直接报 TypeError: navigator.vibrate is not a function。
点击按钮时调用 vibrate 的正确时机
不能在 click 事件回调里无条件调用 navigator.vibrate,尤其当按钮触发页面跳转、表单提交或异步加载时,震动可能被中断或根本没执行——因为部分浏览器要求震动必须由用户**直接交互**(如 touchstart、pointerdown)触发,且需在 500ms 内完成调用。
推荐做法是绑定到 touchstart 或 pointerdown,并立即执行:
button.addEventListener('pointerdown', () => {
if ('vibrate' in navigator) {
navigator.vibrate(30); // 短促震动,避免干扰
}
});
- 用
pointerdown而非click,兼容触摸和鼠标,且触发更早 - 震动时长建议 ≤ 50ms;超过 100ms 容易被系统截断,尤其在后台或低电量模式下
- 避免在
async函数里 await 后再调用,会失去用户手势上下文
vibrate 参数的常见误用
navigator.vibrate 接收两种参数:单个数字(毫秒),或数字数组(交替震动/暂停)。但数组模式有隐藏限制:
- 总时长超过 5000ms 会被浏览器强制截断(Chrome 实测上限约 4999ms)
- 数组长度超过 128 项可能被忽略(部分安卓 WebView 报
InvalidStateError) - 负数、
NaN、undefined会导致整个调用静默失败,不报错也不震动 - 传入
[100, 50, 200]表示「震 100ms → 停 50ms → 震 200ms」,但首次必须是震动(即数组首项必须 > 0)
日常按钮反馈用单数值最稳妥:navigator.vibrate(20) 或 navigator.vibrate(40),别折腾复杂节奏。
为什么点了没反应?几个硬性前提
震动不是“开了就能响”,它依赖三个底层条件同时满足:
- 页面必须处于**前台活跃状态**(tab 未被切换、页面未被冻结)
- 用户已与页面发生**至少一次真实交互**(比如点过某个按钮、滑过区域),否则首次调用会被静默拒绝
- 设备系统设置中**震动功能未被关闭**(Android 设置 → 声音 → 触感反馈;部分厂商还单独控制“网页震动”开关)
如果前两点都确认无误但依然不震,打开手机设置查一下触感反馈是否全局关闭了——这是最容易被忽略的物理层开关。










