/** * haptics.js — navigator.vibrate 震动反馈封装。 * * 预定义震型: * | 名称 | 震型 (ms) | 建议用途 | * |-----------|----------------------|------------------------| * | confirm | [20] | 点按确认 | * | error | [60,40,60] | 操作错误 | * | success | [100] | 过关/成功 | * | warning | [30,50,30,50,30] | 警告/危险逼近 | * | swipe | [10] | 滑动识别成功(最轻) | * | heartbeat | [40,100,40] | 心跳/倒计时紧张感 | * | pickup | [15] | 拾取/获得物品 | * | hit | [80] | 受击/终结性失败 | * | beat | [8] | 节拍锚点(最轻) | * | danger | [25,40,25,40,25] | 危险逼近 | * * 特性检测:'vibrate' in navigator。不支持的平台(iOS Safari 等) * 所有调用静默 no-op,不抛异常。 * * 用法: * import { vibrate } from '../engine/haptics.js'; * vibrate('confirm'); // 预定义名称 * vibrate([50, 30, 50]); // 自定义震型 * * 注意:gesture.js 已内置基础反馈(滑动→swipe,tap/doubletap→confirm), * 游戏逻辑层只需在语义事件(错误/成功/警告等)处自行调用。 */ /** @type {Record} */ export const HAPTIC_PATTERNS = { confirm: [20], error: [60, 40, 60], success: [100], warning: [30, 50, 30, 50, 30], swipe: [10], heartbeat: [40, 100, 40], pickup: [15], hit: [80], beat: [8], danger: [25, 40, 25, 40, 25], }; /** 当前环境是否支持震动(iOS Safari 为 false)。 */ export const hapticsSupported = typeof navigator !== 'undefined' && 'vibrate' in navigator; /** * 触发震动。不支持时静默 no-op。 * @param {keyof typeof HAPTIC_PATTERNS | number[]} pattern 预定义名称或毫秒数组 */ export function vibrate(pattern) { if (!hapticsSupported) return; const p = typeof pattern === 'string' ? HAPTIC_PATTERNS[pattern] : pattern; if (!p) { console.warn('[haptics] 未知震型:', pattern); return; } try { navigator.vibrate(p); } catch (_) { // 某些平台调用即抛(极少见)→ 静默 } } export default vibrate;