navigator.vibrate()必须由用户手势(如touchstart、click)同步触发,不能自动或异步调用;iOS完全不支持,安卓需真机测试,且必须搭配视觉反馈降级。

不能直接让按钮“有震动和触感反馈”——navigator.vibrate() 是独立 API,必须由用户手势显式触发,且不绑定到任何 HTML 元素上;所谓“按钮震动”,本质是监听它的触摸事件,再手动调用震动。
为什么
常见失效不是代码写错,而是触发时机或上下文违规:
-
navigator.vibrate()只能在用户手势事件(如touchstart、click)的同步执行栈中调用;写在setTimeout、fetch.then或页面加载后自动执行里,会静默失败 - Chrome 96+ 要求页面处于前台活跃状态;切到后台再切回来,首次震动需重新由用户手势触发一次
- 部分国产安卓浏览器(如 UC、QQ 浏览器)返回
true却无实际震动,必须真机测试,不能只看返回值 - iOS Safari 完全不支持
vibrate,调用无效且无报错,降级逻辑必须覆盖
怎么安全地在触摸按钮时触发震动
关键不是“给按钮加震动”,而是把震动逻辑塞进它的触摸生命周期里,并兼容中断与节流:
把任意文章或文档内容转换成精美的全屏翻页 HTML 演示文件(幻灯片风格)。当用户发来一篇文章、文档链接、Markdown 内容、或粘贴的文本,并且希望生成演示用的 HTML 时触发。支持任意内容来源:iWiki 链接、KM 链接、本地文件路径、直接粘贴的文本。生成的 HTML 文件保存到本地工作区,并通过企微直接发送给用户。触发词示例:帮我把这篇文章做成PPT、转成演示文档、生成HTML幻灯片、做个演示、转成可以演示的格式、article to deck、make a slide。
- 优先用
touchstart触发,比click延迟更低;避免用touchend(松手才震,反馈滞后) - 参数控制在
[50, 100, 50]这类短脉冲组合,总长 ≤ 5000ms;单次传100比0更可靠(0在某些机型上只是清队列) - 高频连续点击时,系统会自动节流;不要每帧都调
vibrate(),也不用自己做防抖——API 本身已处理 - 务必搭配视觉反馈:给按钮加
:active缩放 + 背景色变深,否则用户根本不知道震动是否生效
如何检测并降级 iOS 和不支持设备
iOS 没有替代方案,伪造震动音效是反模式;唯一合理路径是分层降级:
立即学习“前端免费学习笔记(深入)”;
- 先判断:
if ('vibrate' in navigator && navigator.vibrate)—— 注意有些旧 WebView 有vibrate属性但不可调用,加二次校验更稳 - iOS 用户直接跳过震动逻辑;可用
matchMedia('(prefers-reduced-motion: reduce)')连视觉反馈也关闭 - 不要用
webkit-tap-highlight-color:它只对<a></a>有效,且非标准,iOS 上还可能干扰:active - 如果必须统一反馈体验,唯一可行的是转原生 App,或用 Capacitor 插件桥接系统 Haptic API(仅限 PWA 安装后)
真正难的不是调用 vibrate(),而是让每次震动都有意义:它不该是彩蛋,而应绑定在射击、碰撞、错误确认等明确语义动作上;否则用户很快就会关掉设置,或者误以为设备坏了。


















