iPad上HTML5传感器必然丢帧,因iOS Safari硬限24Hz采样、主线程阻塞导致事件丢失,且无历史数据回填;唯一不丢帧方案是iOS 17.4+启用实验性Sensor API。
iPad 上用 HTML5 读取传感器(如 DeviceMotion 或 DeviceOrientation)时丢帧,不是“能补就补”,而是**必须换采集策略**——原生事件频率受限、JS 主线程阻塞、iOS WebKit 的节流机制共同导致无法靠后处理“补帧”。
requestAnimationFrame + deviceorientation 在 iPad 上必然丢帧iOS Safari 对 deviceorientation 和 devicemotion 事件做了硬性限频:即使设备物理采样率达 100Hz,Web API 最高只触发约 20–30Hz(实测 iOS 17+ 多数为 24Hz),且事件可能被合并或跳过。更关键的是,这些事件在主线程异步派发,若 JS 执行稍慢(比如做数据计算、Canvas 渲染、网络上报),后续事件就会排队或直接丢弃。
event.timeStamp 是派发时间,不是传感器原始采样时间requestAnimationFrame 的刷新节奏(通常 60fps)和传感器事件节奏不同步,强行对齐只会放大抖动setTimeout / setInterval 的“插值补帧”都是伪需求——你补的不是传感器数据,是猜出来的假数据Navigator.getSensor()(仅限 iOS 17.4+)iOS 17.4 起,Safari 实验性支持标准 Sensor API(需开启实验特性),可绕过旧事件模型,获得更高频、更稳定的原始采样流。这是目前唯一接近“不丢帧”的路径:
if ('Accelerometer' in window) {
const accel = new Accelerometer({ frequency: 60 });
accel.addEventListener('reading', () => {
console.log(accel.x, accel.y, accel.z); // 真实 60Hz 原始数据
});
accel.start();
}
如果你必须支持 iOS 15/16,放弃“补帧”,转而做三件事:压低目标帧率、减少主线程负担、用缓存缓冲抖动:
devicemotion 但只取 accelerationIncludingGravity,避免解析 rotationRate 增加开销performance.now() 记录每次事件真实到达时间,不依赖 event.timeStamp
console.log、避免频繁 DOM 操作,把传感器逻辑抽离到 Web Worker(iOS 16.4+ 支持 Accelerome
ter 在 Worker 中使用)丢帧的本质是平台限制,不是代码写得不够巧。所谓“补帧”,在 iOS Web 环境里,99% 的场景下只是把问题藏得更深而已——盯住可用采样率、控制 JS 负载、接受合理延迟,比任何插值算法都管用。