Worker无法直接读取传感器数据,须由主线程采集预处理后以Float32Array零拷贝传入;Worker仅对整段步进序列做自相关或简化FFT分析,输出步频、置信度等结构化结果,并设超时降级与多实例并行机制。

不能直接在 Worker 中读取传感器原始数据,必须由主线程采集后传入。Worker 只负责对已采集的步进序列做异步频谱分析、周期检测和特征提取,避免阻塞 UI。
主线程完成传感器数据采集与预处理
iOS 和 Android 浏览器对 deviceorientation/devicemotion 有硬性限频(实测约 20–30Hz),且事件可能合并或丢失。因此不依赖实时事件流,而采用“采样快照 + 批量上传”策略:
- 主线程用
requestAnimationFrame或setInterval(..., 16)驱动稳定采样节奏,每次调用performance.now()记录时间戳,并缓存accelerationIncludingGravity三轴值 - 积累满 N 条(如 500–2000 点)后,打包为
Float32Array:[t₀,x₀,y₀,z₀, t₁,x₁,y₁,z₁, …] - 通过
postMessage(data, [data.buffer])使用 Transferable Objects 零拷贝发送给 Worker,避免序列化开销
Worker 内执行轻量但稳定的频率分析
Worker 不做实时流式计算,而是对整段步进时序做离散傅里叶变换(DFT)或更实用的自相关分析(Auto-correlation),识别主频与步频节律:
- 优先使用自相关:对 Z 轴加速度序列做滑动点积,峰值位置对应步行周期(单位:样本数),再结合时间戳换算为 Hz(如峰值在第 42 样本,采样间隔 33ms → 周期 ≈ 1.386s → 步频 ≈ 0.72Hz)
- 若需频域细节,可用简化版 FFT(如 Cooley-Tukey 实现,仅支持 2 的幂长度),输入限制在 1024–2048 点;输出取前 128 个 bin,映射 0–5Hz 步行常见频段
- 结果结构化返回:
{ stepFreqHz: 0.72, confidence: 0.86, strideCount: 14, cadenceBpm: 43 }
规避平台限制与提升鲁棒性
iOS Safari 目前(2026 年)仍不支持 Navigator.getSensor() 在所有场景启用,且实验性 API 需用户手动开启。因此当前最稳路径仍是兼容方案:
立即学习“前端免费学习笔记(深入)”;
- 不尝试在 Worker 中调用
DeviceMotionEvent—— 它不可访问,会报ReferenceError - 主线程采集时增加低通滤波(如一阶 IIR)平滑噪声,再传入 Worker,减少无效高频扰动对周期检测干扰
- Worker 分析超时保护:用
performance.now()监控单次分析耗时,若 >30ms 自动降级(如跳过 FFT,只跑自相关) - 多段分析可并行:启动多个 Worker,每段数据分发给独立实例,主线程聚合最终步频统计(均值、方差、趋势)
不复杂但容易忽略:步频分析效果高度依赖原始采样质量,与其花力气补帧或插值,不如在主线程做好触发时机对齐(如绑定到 requestAnimationFrame)、剔除静止段、归一化幅度,再交由 Worker 稳定运算。



















