做了个什么东西
去年换工作后通勤变成骑车,单程 6 公里。骑了两个月我发现自己每天走的路线几乎一模一样,偶尔绕路买杯咖啡就算"探索"了。试了几个运动记录 App,不是卷配速就是搞社交排行榜,没有一个能满足我最简单的需求:把我走过的地方可视化出来,像游戏里的战争迷雾,走过就亮。
找了一圈没满意的,干脆自己写了一个。App 叫「像素征途」,v1.0 已上架 App Store,iOS 16+。下面聊聊技术实现过程中几个比较有意思的点。
地图格子化方案
核心思路是把地图按经纬度切成像素级格子,每个格子大约 50m×50m。用户经过一个格子就点亮它,重复经过就给格子升级。走了五次以上变成金色,我管它叫"金色大道"——基本上你的通勤路线最后会变成一条发光的线。
这个粒度是反复试出来的。太大(比如 200m)没有探索感,太小(比如 10m)则 GPS 抖动会导致误点亮,而且存储压力也大。50m 在城市场景下体感比较合适,一条街道大概 2-3 个格子宽。
后台定位的省电策略
这是踩坑最多的部分。iOS 后台定位如果一直用 GPS 精度,电量根本扛不住。我最后做了三档模式切换:
enum TrackingMode: Int {
case powerSave = 0 // significantLocationChanges, 几乎不耗电
case balanced = 1 // 100m精度 + visit monitoring
case continuous = 2 // GPS精度, 骑行/步行时用
}
func applyMode(_ mode: TrackingMode) {
locationManager.stopUpdatingLocation()
switch mode {
case .powerSave:
locationManager.startMonitoringSignificantLocationChanges()
case .balanced:
locationManager.desiredAccuracy = kCLAccuracyHundredMeters
locationManager.allowsBackgroundLocationUpdates = true
locationManager.startUpdatingLocation()
case .continuous:
locationManager.desiredAccuracy = kCLAccuracyBest
locationManager.allowsBackgroundLocationUpdates = true
locationManager.startUpdatingLocation()
}
}
省电模式用 significantLocationChanges,基站级精度,基本零功耗但格子点亮会粗糙一些。平衡模式适合日常通勤,实测一天掉电不到 5%。持续模式给骑行和 citywalk 用,精度最高但费电。
实际使用中我自己日常挂平衡模式,周末出去逛的时候手动切持续模式,这个组合对我来说够用了。
高铁场景的特殊处理
这个坑完全没预料到。时速 300 公里时 GPS 漂移严重,而且频繁跨基站会导致 significantLocationChanges 疯狂回调。我加了速度过滤和卡尔曼平滑,速度超过 200km/h 时自动降低采样频率但不停止记录,这样坐高铁也能看到沿途格子被点亮,只是精度会低一些。
说实话高铁这个场景优先级不高,但作为一个出差偶尔坐高铁的人,看到京沪线慢慢被点亮还是挺有成就感的。
用养成系统解决"一周就腻"的问题
单纯点亮格子我自己测试一周就腻了。所以加了一套轻量养成系统:把地图切成 8×8 的大区块叫"领地",一个领地内点亮 60% 格子就算征服。征服领地给经验值,经验值解锁科技树(比如"远征者"分支解锁后,单次出行超过 5km 有额外奖励格子)。还有徽章系统,类似成就,比如"连续 30 天出门""征服 10 个领地""金色大道累计 50 条"。
这些设计的出发点很简单:让日常出行本身变成游戏进度,不需要刻意去运动、不需要跟别人比。你正常上下班,进度条就在涨。
关于隐私的选择
所有数据存本地 CoreData,没有服务器,没有账号系统。我自己很在意位置隐私,做这个 App 的时候就决定不碰用户轨迹数据。坏处是换手机需要手动导出备份,好处是你的行踪只有你自己知道。
这个决定也让开发简单了很多——不用写后端、不用处理数据合规,一个人就能维护。
后续计划
目前功能基本完整,后续想加两个东西:一个是时间维度的回放,能看自己一年内地图亮起来的过程;另一个是 widget 展示当日点亮数。
如果你也在做定位相关的 App,或者对省电策略有更好的方案,欢迎在评论区聊聊。特别是 Android 那边后台定位的限制比 iOS 还恶心,不知道有没有同行踩过类似的坑。