
地图类程序前端——使用阈值和噪声过滤算法处理平滑 UI

本文简要记录了我在解决某一款企业级地理信息类微信小程序时候,处理定位点随机抖动的过程。由于 GPS 精度、信号强度等各种不可控因素,采集到的经纬度信息往往会产生大量偏差造成抖动,我用阈值和 OEF 算法有效解决了这个问题。
Discard 逻辑:异常漂移点过滤
该过滤逻辑仅是在前端提前粗过滤,为了减轻传输量、优化实时 UI 体验,但是如果要兼顾反作弊、异常监测等需求,后端也应该做出类似的逻辑来决定坐标点是否录入。
我设计了三层阈值,简要概括为:
- 速度不能超过人类越野跑速度阈值 6 m/s
- 加速度不能超过人类的瞬时加速度阈值 4 m/s²
- 最低 10 m 阈值确保不会因为 GPS 抖动而大量上传。
设定阈值:
1 | uploadGeometry: function(currentLocation,allCheckedIn) { |
计算速度和加速度的核心算法:
1 | // 计算时间差、速度、加速度 |
OEF 算法:消锯齿平滑处理
刚才的速度/加速度阈值只能“剔除离谱点”,但剩下的坐标虽然在合理阈值内, GPS 的随机抖动仍然会让线路锯齿、距离累计偏大。
我在网上找到了两种算法,最终选择了 OEF 算法处理。
OEF 算法核心实现可参考:Noise Filtering Using 1€ Filter | Jaan Tollander de Balsch
- 卡尔曼滤波算法如果想在前端纯手写,动辄需要几十行矩阵式推导,虽然可以引用第三方库,但是对于微信小程序来说整合也麻烦。不过值得一提的是,后端的再次校验时可以采用这种算法,来配合前端达到更好效果。
- OEF 算法更轻量,计算速度更具实时性, 适合移动端小程序环境。所以我在前端写了一个工具类实现这个算法。
我创建的工具类,放在了 utils\one-euro-filter.js
,算法核心如下:
1 | function alphaCalc(cutoff,freq){ ... } // 根据截止频率求 α |
与上文的 discard 逻辑的协同
OEF 在 10 m 内随机抖动 场景下生效:
• 抖动 → 平滑后基本被“压扁”,距离累积不再反复 +1 m、-1 m
• 真正的大位移 (>10 m) 仍会输出明显变化,被后面 uploadGeometry 捕获并进入速度/加速度阈值判定(仍能过滤“飞跃点”)。
最终效果
每只滤波器内部会保存 lastTime / lastValue / deriv(速度的一阶导),随后对每次输入做自适应计算。
-
UI 轨迹线更顺滑、不锯齿
-
距离累积趋于真实(不被高频噪声放大)
-
不引入明显延迟(每次计算只需常数级乘加运算)
参数调节
alphaCalc(cutoff, freq)
minCutoff
控制静态/慢速时的平滑强度;freq
会影响beta
,beta 越大,响应越灵敏(平滑程度越低,延迟越小)。
现在用 1.0 / 0.0
做保守平滑,可根据体验提高 beta
至 0.005-0.02
使转弯曲线更“跟手”。
onLoad
函数里:
1 | // 初始化定位平滑滤波器(freq 无需指定,会根据每次采样动态计算) |
实测验证
下面两张图分别是优化前和优化后的相同路线下的测试。
- 标题: 地图类程序前端——使用阈值和噪声过滤算法处理平滑 UI
- 作者: 三葉Leaves
- 创建于 : 2025-07-10 00:00:00
- 更新于 : 2025-07-10 13:51:54
- 链接: https://blog.oksanye.com/c147aa44710c/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。