必须用 devicemotionevent 实现“摇一摇抽奖”,因 accelerometer api 需 https、用户手势激活且 ios safari 和微信 x5 内核不支持;devicemotionevent 兼容性广,通过检测加速度变化率(非绝对值)判定摇动,配合节流、防抖和阈值判断即可稳定运行。

直接用 Accelerometer API 实现“摇一摇抽奖”在当前主流浏览器中不可行——因为 Accelerometer 是 Web Sensor API 的一部分,需 HTTPS、用户手势激活,且仅 Chromium 101+(桌面/安卓)有限支持,iOS Safari 和旧版 Android 完全不支持。实际项目中,必须退回到兼容性更好、支持更广的 DeviceMotionEvent来实现稳定可靠的摇一摇交互。
为什么不用 Accelerometer 而用 DeviceMotionEvent
Accelerometer 接口虽更精准(能排除重力、提供 raw 加速度),但存在三大硬性限制:
- 需要页面运行在 HTTPS 环境下(HTTP localhost 除外)
- 首次使用前必须由用户显式触发(如点击按钮)才能请求传感器权限
- iOS 全系 Safari 不支持,微信内置浏览器(X5 内核)也不支持
而 DeviceMotionEvent 自 2012 年起就被 iOS Safari、Android Chrome、微信 WebView 广泛支持,只需监听加速度变化即可满足摇一摇判定需求,是当前唯一实用选择。
核心原理:用加速度变化率识别“摇动”
摇一摇不是检测绝对加速度值,而是捕捉短时间内的剧烈变化。设备静止时,accelerationIncludingGravity 的 x/y/z 值接近恒定(约 0, 0, 9.8);快速晃动时,三轴值会在毫秒级内大幅波动。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
关键计算逻辑:
- 每 100ms 左右采样一次(防高频抖动误触)
- 计算本次与上次三轴和的差值绝对值:
Math.abs((x+y+z) - (last_x+last_y+last_z)) - 除以时间差再放大系数(如 ×10000),得到等效“摇动速度”
- 超过阈值(常见 2500–4000)即判定为有效摇动
完整可运行代码(含防抖+抽奖逻辑)
以下代码已适配微信、QQ、主流安卓/iOS 浏览器:
let lastTime = 0;
let lastX = lastY = lastZ = 0;
const SHAKE_THRESHOLD = 3200;
let isShaking = false; // 防连击
<p>function startShake() {
if (!window.DeviceMotionEvent) {
alert('您的设备不支持摇一摇');
return;
}</p><p>function handleMotion(e) {
const { x, y, z } = e.accelerationIncludingGravity || {};
if (x === null || y === null || z === null) return;</p><pre class="brush:php;toolbar:false;"><pre class="brush:php;toolbar:false;">const now = Date.now();
if (now - lastTime SHAKE_THRESHOLD && !isShaking) {
isShaking = true;
triggerLottery(); // 执行抽奖
setTimeout(() => isShaking = false, 800); // 锁定800ms防重复
}
lastTime = now;
lastX = x; lastY = y; lastZ = z;}
window.addEventListener('devicemotion', handleMotion, { passive: true }); }
function triggerLottery() {
const prizes = ['谢谢参与', '5元红包', 'iPhone 16', '100元话费', '再来一次'];
const winner = prizes[Math.floor(Math.random() * prizes.length)];
alert(? 恭喜!抽中:${winner}
// 页面加载后需用户点击一次来激活传感器(iOS/微信强制要求) document.getElementById('start-btn').addEventListener('click', () => { startShake(); this.textContent = '已开启摇一摇'; });
增强体验的关键细节
光有逻辑不够,真实活动页还需这些优化:
-
视觉反馈:摇动时给容器添加 CSS shake 动画类(如
animation: shake 0.5s) -
声音提示:用
new Audio('shake.mp3').play()播放短促音效(注意 iOS 需用户手势后才可播放) - 失败兜底:若 5 秒内无响应,提示“请确保手机开启了运动传感器”并引导检查系统设置
- 抽奖去重:结合后端生成唯一 token 或限制 IP/设备号每日次数,避免刷奖
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










