4.7 KiB
罗盘问题排查记录
文档版本:v1.0 最后更新:2026-04-02
背景
本项目在微信小程序中使用罗盘驱动:
- 指北针针头
- 指北针顶部角度数字
heading-up自动转图
在一次围绕顶部提示窗、传感器显示链和性能优化的修改后,出现了以下问题:
- iOS 端偶发正常,偶发异常
- Android 端罗盘长期无样本
- 指北针不转
heading-up自动转图一起失效
最终结论
这次问题的主因不是算法本身,而是:
Android 微信环境下,罗盘监听需要被持续保活;之前将多处看似冗余的 compassController.start() 清理掉后,Android 的罗盘样本链被破坏了。
也就是说:
- iOS 对罗盘监听更宽容
- Android 对罗盘监听更脆弱
- 之前稳定,不是因为链路更“干净”,而是因为老代码里存在一条实际有效的“罗盘保活链”
现象总结
失效期
- Android 调试面板里
Compass Source为无数据 - iOS 仍可能有
罗盘样本 - 若强行用
DeviceMotion兜底,会出现:- 指针会转
- 但方向不准
- 自动转图方向错误
恢复后
- Android
Compass Source恢复为罗盘 - 指北针针头恢复
- 顶部角度数字恢复
heading-up恢复
误判过的方向
以下方向在本次排查中都被考虑过,但最终不是根因或不是主要根因:
1. DeviceMotion 兜底方案
问题:
DeviceMotion可以给出设备姿态角- 但不能稳定代替“指向北”的绝对罗盘
- 用它兜底会导致:
- 能转
- 但方向明显不准
结论:
DeviceMotion 不能作为正式指北针来源。
2. 加速度计 / 其他传感器互斥
曾排查:
AccelerometerGyroscopeDeviceMotionCompass
结论:
- 加速度计在当前微信 Android 环境下不稳定,已放弃
- 但这不是这次罗盘彻底失效的主因
3. 算法问题
曾尝试调整:
- 角度平滑
- 设备方向单位解释
- motion fallback 算法
结论:
这些会影响“顺不顺”、“准不准”,但不能解释 Android 完全无罗盘样本。
真正修复的方法
将之前被清理掉的多处 this.compassController.start() 恢复回去。
这些调用点主要分布在:
commitViewport(...)handleTouchStart(...)animatePreviewToRest(...)normalizeTranslate(...)zoomAroundPoint(...)handleRecenter(...)handleRotateStep(...)handleRotationReset(...)
这些调用在代码审美上看起来像“重复启动”,但在 Android 微信环境里,它们实际上承担了:
重新拉起 / 保活罗盘监听
的作用。
当前工程判断
本项目当前应当采用以下原则:
1. 罗盘主来源只使用 Compass
不要再让:
DeviceMotion- 其它姿态角
参与正式指北针和自动转图的主方向链。
2. DeviceMotion 只保留为辅助或调试输入
可用于:
- 调试面板显示
- 设备姿态观察
- 未来原生端姿态融合参考
但不要直接驱动指北针。
3. Android 端罗盘需要保活
后续不要再把这些 compassController.start() 当成纯冗余逻辑随意清掉。
如果要优化代码,应该:
- 保留现有行为
- 将其收口为有明确语义的方法
例如:
ensureCompassAlive()refreshCompassBinding()
而不是直接删掉。
与生命周期相关的硬约束
以下约束必须保持:
单实例
页面层必须保证任意时刻只有一个 MapEngine 活跃实例。
完整销毁
MapEngine.destroy() 中必须完整执行:
compassController.destroy()- 其它传感器
destroy()
防止旧监听残留。
调试状态不应影响罗盘主链
调试面板开关不应再控制:
- 罗盘是否启动
- 罗盘是否停止
否则容易再次引入平台差异问题。
推荐保留的调试字段
以下字段建议长期保留,便于后续定位:
Compass SourcesensorHeadingText- 顶部角度数字
heading-up开关状态
其中 Compass Source 至少应显示:
罗盘无数据
避免再次将问题误判为算法问题。
后续优化建议
如果后面要继续优化这段代码,推荐方向是:
可做
- 将分散的
compassController.start()收口成命名明确的方法 - 为 Android 罗盘链补一层更可读的“保活机制”注释
- 保留当前稳定行为前提下做重构
不建议
- 再次移除这些重复
start()调用 - 用
DeviceMotion正式兜底指北针 - 让调试开关影响罗盘主链启动
一句话经验
在微信小程序里,Android 罗盘监听的稳定性比 iOS 更脆;某些看似冗余的 start() 调用,实际是平台兼容补丁,不应该在没有真机回归的情况下清理。