HTML5无标准加速度计接口,主流浏览器通过实验性Generic Sensor API的Accelerometer类支持,仅限HTTPS/localhost安全上下文且需用户授权,移动端兼容性优于桌面端;iOS Safari不支持。

HTML5 并没有标准的 Accelerometer 接口。目前主流浏览器(Chrome、Edge、Firefox 等)支持的是 Generic Sensor API 中的 Accelerometer 类,但它属于实验性功能,**仅在安全上下文(HTTPS 或 localhost)中可用,且需用户授权(如开启运动传感器权限),移动端支持远优于桌面端**。直接“检测剧烈震动并自动报警”需谨慎设计,避免误触发和权限拒绝。
确认浏览器兼容性与权限前提
不是所有设备和浏览器都支持 Accelerometer。必须先检查:
- 当前是否为 HTTPS 或
localhost(否则 API 不可用); - 调用前需用户主动交互(如点击按钮)才能请求传感器权限;
- 使用
navigator.permissions.query({ name: 'accelerometer' })检查权限状态; - Chrome/Edge 92+ 支持,Firefox 部分版本需启用
dom.genericSensor.enabled;iOS Safari 不支持该 API。
获取加速度数据并识别“剧烈震动”
震动本质是加速度模值(Math.sqrt(x² + y² + z²))在短时间内显著偏离重力基准(≈9.8 m/s²)并伴随高频波动。不能只看单次峰值,需结合窗口滑动计算:
- 以 60Hz 左右频率读取
accelerometer.x、y、z; - 计算瞬时合加速度
accTotal = Math.sqrt(x*x + y*y + z*z); - 维护一个长度为 10–20 的滑动窗口,记录最近若干次的
accTotal; - 当当前值 > 基准均值 + 阈值(如 4–6 m/s²),且连续 3–5 帧超限,才判定为“剧烈震动”;
- 建议基准均值用静止几秒后的初始平均值,或低通滤波动态估算。
实现轻量报警逻辑(不依赖后端)
纯前端报警应克制,优先保障用户体验和隐私:
- 触发后立即
vibrate([200, 100, 200])(需navigator.vibrate权限,仅 Android 支持); - 播放本地短音频(需预加载,避免自动播放策略拦截);
- 页面顶部显示非阻塞式提示(如
toast),3 秒后自动消失; - 禁止自动拨号、发短信或上传位置——这些需明确用户操作且涉及敏感权限,不可“自动”执行。
代码片段示意(含错误防护)
以下为简化但健壮的核心逻辑:
let accelerometer;
let history = [];
const WINDOW_SIZE = 15;
const THRESHOLD = 5.0; // m/s² above baseline
let baseline = 9.8;
<p>async function startShakeDetection() {
if (!('Accelerometer' in window)) {
console.warn('Accelerometer not supported');
return;
}</p><p>try {
// 必须由用户手势触发(如按钮点击)
accelerometer = new Accelerometer({ frequency: 60 });
accelerometer.addEventListener('reading', handleReading);
accelerometer.start();
} catch (err) {
console.error('Failed to start accelerometer:', err.name);
}
}</p><p>function handleReading() {
const acc = Math.sqrt(
this.x <strong> 2 + this.y </strong> 2 + this.z ** 2
);</p><p>history.push(acc);
if (history.length > WINDOW_SIZE) history.shift();</p><p>if (history.length >= WINDOW_SIZE) {
const avg = history.reduce((a, b) => a + b, 0) / history.length;
if (acc > baseline + THRESHOLD &&
acc > avg * 1.3) { // 额外相对增幅过滤
triggerAlert();
// 重置历史,防连续误报
history = [];
}
}
}</p><p>function triggerAlert() {
if ('vibrate' in navigator) navigator.vibrate([150]);
document.getElementById('alert-toast').style.display = 'block';
setTimeout(() => {
document.getElementById('alert-toast').style.display = 'none';
}, 3000);
}</p>前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











