
简介微信跑步小程序源码是一份面向微信小程序初学者的完整实战项目以跑步追踪与数据记录为场景解决从零搭建运动健康类应用时的页面组织、数据同步和设备能力接入问题。资源共20个文件包体仅12KB核心包含WXML页面结构、WXSS样式、JavaScript业务逻辑、JSON项目配置以及图标与说明文档整体目录结构简洁紧凑适合逐文件拆解学习。源码覆盖Page路由、setData响应式更新、本地存储、wx.getLocation定位、加速度计计步、事件绑定、UI组件组合等关键知识点并展示了公共工具模块、自定义图标素材与说明文档的组织方式也涉及开发者工具调试、用户授权等实操环节由于体积小巧可快速上手修改适合作为课程设计或原型开发的基础。已有1972人学习下载尤其适合正在准备毕业设计、小程序竞赛或想转前端开发的读者以此为起点进一步扩展健身打卡、户外运动等场景。 最近不少人来问“微信跑步小程序源码”有拿去做毕业设计的有想在公司项目里加一个运动记录模块的还有打算直接做成跑步社区产品的。我前前后后做过几个运动类小程序从最基础的轨迹记录、数据统计到后来的付费课程报名、跑友排行榜基本把微信小程序里跟定位、地图、支付相关的坑都踩过一遍。这篇就把这些经验整理出来尽量给你一套看得懂、能上手的思路和代码而不是丢一个光秃秃的源码包让你自己猜。如果你正在找源码参考或者打算自己从零写一个跑步类小程序这篇文章基本就是按“需求拆解 → 技术选型 → 核心实现 → 问题排查”的顺序来聊不管你是前端新手还是写过几个小项目的开发者都能在里面找到能直接用的东西。1. 起步之前先想清楚你要做什么样的跑步小程序1.1 需求拆解跑步小程序的核心功能边界跑步类小程序和商城、工具类小程序不太一样它的核心是“记录一段运动过程并把数据可视化地还给用户”。用户打开小程序开始跑步结束时看到一条轨迹、一组数据这个体验闭环就算成立了。如果把一个跑步小程序比作一套完整产品最基础的功能边界大致是这几块运动记录开始、暂停、继续、结束这是整个小程序的骨架。定位与轨迹拿到用户的经纬度在地图上画出跑步路线。数据统计距离、时长、配速、卡路里这是用户最关心的数字。历史记录保存每一次运动用户可以回看。个人中心微信授权登录展示头像昵称和累计运动数据。进阶一点的功能比如跑步计划、排行榜、社区打卡、付费课程报名都属于在上面这个底座上加东西。我见过不少初次做这个项目的朋友一上来就想把排行榜、动态、社交全塞进去结果光定位和轨迹就折腾了两周。我的建议是第一个版本先把“开始跑步 → 记录轨迹 → 结束出数据 → 存进历史”这条主链路跑通其他都是后话。1.2 技术选型原生小程序、uni-app 还是 Taro这个选择题几乎每个想做跑步小程序的人都会遇到。直接从我的经验说结论如果这个项目是你一个人的毕设或者练手项目建议用原生微信小程序如果你是想跨端复用而且你本身熟悉 Vue可以用 uni-app如果你的团队是 React 技术栈Taro 更顺一些。原生小程序的好处是微信提供的能力包装得最直接定位、地图、支付这些 API 都是第一手对接遇到问题搜资料也最好搜。uni-app 和 Taro 确实能跨端但运动类小程序对定位和地图渲染的要求比较高跨端框架在这两块偶尔会有 API 透传不完整的情况出了问题反而更难排查。另外提醒一句如果你想基于别人的源码改先看清楚它是原生还是 uni-app两者目录结构和构建方式差别很大硬改很容易把自己绕晕。HBuilder 打开原生小程序项目时会提示“不是开发者”之类的问题多半也是工程类型不匹配导致的。1.3 后端方案云开发还是自建服务后端选型决定你后面省不省心。微信云开发云函数 云数据库对个人项目和毕设非常友好不需要自己买服务器、配域名、搞 HTTPS云函数里可以直接调用微信上下文登录态也帮你处理好了。轨迹数据量不大的情况下云数据库完全扛得住。如果你的项目要上生产或者以后还想做 App、Web 端后端建议用 Node.js 或 Java 单独拆服务。原因很简单云开发虽然方便但数据库查询能力相对基础报表统计、复杂权限控制、和其他系统对接时自建服务的灵活度会高很多。我个人的做法是原型阶段用云开发等核心功能稳定了再把接口迁移到独立后端。前端代码可以做到无感切换只要把请求层封装好就行。2. 核心功能的技术拆解轨迹、数据、权限2.1 定位能力getLocation 与后台持续定位跑步小程序最核心的能力就是定位。微信小程序里和定位相关的接口有三个很多人分不清wx.getLocation单次定位适合获取当前坐标。wx.startLocationUpdate持续监听位置变化适合跑步过程中实时获取坐标。wx.startLocationUpdateBackground后台持续定位适合小程序切入后台后依然记录轨迹。跑步场景下通常流程是用户点击开始 → 调用 wx.getLocation 拿到起点 → 调 wx.startLocationUpdate 持续监听位置变化 → 结束时 wx.stopLocationUpdate 停止监听。这里有个大坑也是很多源码跑不起来的根本原因光在代码里调用接口是不够的必须在 app.json 里声明权限和隐私接口。低版本基础库和真机上缺少声明会直接导致定位失败或者拿不到经纬度。app.json 里至少要这样配置{ permission: { scope.userLocation: { desc: 您的位置信息将用于记录跑步轨迹 } }, requiredPrivateInfos: [getLocation, startLocationUpdate] }如果你需要后台定位还要在 app.json 的 requiredBackgroundModes 里声明 location{ requiredBackgroundModes: [location] }注意这个配置一旦声明微信审核时会重点检查你的定位用途是否合理。跑步类小程序声明后台定位可以解释为“熄屏或切后台时持续记录运动轨迹”这是说得通的。但如果你的小程序和运动八竿子打不着却申请了后台定位基本会被打回。2.2 轨迹生成与地图渲染轨迹的呈现方式是用 map 组件加上 polyline 属性。基础思路是把定位监听回调里拿到的经纬度点一个个 push 到数组里然后通过 setData 更新给 map 组件polyline 就会把这些点连成一条线。代码层面大致是这个结构map idrunMap latitude{{latitude}} longitude{{longitude}} polyline{{polyline}} show-location /mapthis.setData({ polyline: [{ points: this.data.trackPoints, color: #FF6B35, width: 5, borderColor: #FFFFFF, borderWidth: 1 }] });但 GPS 数据有一个很头疼的问题漂移。原地不动时GPS 点也会小幅跳动跑到高楼或树荫下一个点可能瞬间“飞”出去几十米。如果不做处理轨迹画出来就是一团乱麻。常见的处理办法是加一个距离阈值比如相邻两个点之间的距离小于 5 米就忽略大于某个不合理的值比如 100 米也忽略因为正常跑步几百毫秒内不可能位移这么远。2.3 运动数据计算距离、配速、卡路里距离不推荐直接读取定位接口返回的 speed 字段累加那个值在不同手机上差异很大。最稳的做法是用 Haversine 公式根据两个经纬度点算球面距离再把所有相邻点之间的距离累加起来。Haversine 公式的实现不难跑起来大概是这样的function getDistance(lat1, lng1, lat2, lng2) { const R 6371000; const rad Math.PI / 180; const dLat (lat2 - lat1) * rad; const dLng (lng2 - lng1) * rad; const a Math.sin(dLat / 2) * Math.sin(dLat / 2) Math.cos(lat1 * rad) * Math.cos(lat2 * rad) * Math.sin(dLng / 2) * Math.sin(dLng / 2); const c 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); return R * c; }配速的计算方式是运动时间除以距离单位通常写成“分/公里”比如跑 5 公里用了 30 分钟配速就是 6 分 00 秒。卡路里一般用 MET 值估算跑步的 MET 值大概在 9.8 左右公式是 卡路里 MET × 体重(kg) × 时间(小时)这个数值是估算值够用但别当成医学参考。还有个细节暂停运动的时候不能继续往轨迹数组里 push 点否则暂停期间的位置晃动会变成一条难看的短横线。暂停时要停止监听或者打个暂停标记恢复时再继续记录。3. 实战实现从零搭建跑步记录核心模块3.1 项目结构与权限配置假设我们用原生微信小程序来搭目录结构可以分成几个清晰的部分├── app.js ├── app.json ├── pages/ │ ├── index/ // 首页展示快捷入口 │ ├── run/ // 跑步记录页核心页面 │ └── history/ // 历史记录页 ├── utils/ │ ├── gps.js // 距离计算、轨迹去噪 │ ├── format.js // 时间、配速格式化 │ └── storage.js // 本地存储封装 └── components/ └── stat-card/ // 数据展示卡片app.json 里除了权限声明还要配置页面路径和 window 样式。这里有一个容易被忽略的点运动页面的导航栏最好设置成自定义因为跑步过程中需要大数字展示实时配速和距离默认导航栏会占掉一部分屏幕空间自定义导航栏能让界面更沉浸。3.2 核心代码运动状态机与轨迹记录跑步页面的核心逻辑本质上是一个状态机空闲、跑步中、暂停中、已结束。每一次状态切换都有对应的入口和出口。我习惯把状态和核心参数放在 data 里统一管理。Page({ data: { status: idle, // idle | running | paused | finished distance: 0, duration: 0, pace: 000\, trackPoints: [], latitude: 0, longitude: 0 }, startRun() { wx.getLocation({ type: gcj02, success: (res) { this.setData({ status: running, latitude: res.latitude, longitude: res.longitude, trackPoints: [{ latitude: res.latitude, longitude: res.longitude }] }); this._startWatch(); this._startTimer(); } }); }, _startWatch() { this._watchListener (res) { const point { latitude: res.latitude, longitude: res.longitude }; // 去噪距离过近或异常跳变的点直接忽略 const last this.data.trackPoints[this.data.trackPoints.length - 1]; const d getDistance(last.latitude, last.longitude, point.latitude, point.longitude); if (d 5 || d 100) return; const distance this.data.distance d; const duration this.data.duration; const pace duration / 60 / (distance / 1000); this.setData({ trackPoints: [...this.data.trackPoints, point], distance, pace: formatPace(pace) }); // 更新地图视野 this.setData({ latitude: point.latitude, longitude: point.longitude }); }; wx.startLocationUpdate({ success: () { wx.onLocationChange(this._watchListener); } }); }, pauseRun() { this.setData({ status: paused }); wx.stopLocationUpdate(); clearInterval(this._timer); }, resumeRun() { this.setData({ status: running }); this._startWatch(); this._startTimer(); }, endRun() { wx.stopLocationUpdate(); clearInterval(this._timer); // 保存记录到本地再异步同步到云数据库 const record { distance: this.data.distance, duration: this.data.duration, pace: this.data.pace, track: this.data.trackPoints, date: Date.now() }; saveRecord(record); this.setData({ status: finished }); } });几个关键点再强调一下暂停时一定要 stopLocationUpdate因为微信的持续定位是比较耗电的操作长时间挂着对用户手机不友好而且也会影响状态判断。计时器用 setInterval 每秒更新一次 duration但 UI 里的距离和配速不要每秒都 setData。setData 太重频繁更新会导致页面卡顿尤其是轨迹点数组越来越长之后。我习惯把轨迹绘制和数据展示拆开轨迹每 3-5 秒更新一次数据和配速每秒更新一次。跑完的轨迹数据不要无脑存全量点一小时跑下来可能有三四千个点直接存数据库压力不小。建议做抽稀处理比如每 10 个点保留 1 个或者用简单的距离抽稀——相邻点距离小于 8 米就丢弃。这样轨迹形状基本不变数据量能减少一大半。3.3 延伸需求微信支付v3对接要点如果你做的是带付费功能的跑步小程序比如赛事报名、付费训练课程就绕不开微信支付。这里简单聊一下 v3 对接的核心流程这部分在源码项目里也是经常被问到的。微信支付 v3 的流程分两步第一步是后端向微信支付统一下单接口发起请求拿到预支付交易会话标识第二步是后端把参数返回给小程序前端前端调 wx.requestPayment 拉起支付。后端统一下单时签名串的格式是HTTP方法\n 请求路径\n 请求时间戳\n 请求随机串\n 请求报文主体\n这个签名串很容易拼错每一项后面都有一个换行符而且最后一项报文主体后面也要有换行。用商户私钥做 SHA256withRSA 签名后放到 Authorization 头里。小程序端拿到参数后这样调用wx.requestPayment({ timeStamp: data.timeStamp, nonceStr: data.nonceStr, package: data.package, // 格式为 prepay_idxxx signType: RSA, paySign: data.paySign, success: () { // 支付成功 }, fail: () { // 支付失败或取消 } });支付回调是最容易出问题的地方。支付结果通知会通过 POST 请求发到你配置的回调地址报文里的 resource 字段是 AES-256-GCM 加密的需要用 APIv3 密钥解密解密后才能拿到订单号、支付状态这些信息。很多同学在回调里卡了好几天基本都是这里。如果遇到“支付功能暂时无法使用”的提示先别急着改代码。先排查三件事商户号主体是否和小程序主体一致、小程序类目是否包含需要支付能力的类目、账户有没有被平台限制。确认是限制问题的话只能按平台要求整改后申诉不要试图绕过去那只会把问题越搞越大。4. 常见问题与排查实录4.1 定位与轨迹相关的坑定位这块我遇到的坑可以列一个小表格方便你对照排查现象常见原因解决办法真机上 getLocation 直接走 failapp.json 未声明 permission 或 requiredPrivateInfos补全配置重新编译模拟器定位不准轨迹乱画模拟器 GPS 模拟能力有限尽量用真机调试用户拒绝授权后无法恢复未提供引导重新授权入口调 wx.openSetting 引导用户打开位置权限轨迹出现“飞点”GPS 漂移或遮挡导致异常跳变加距离阈值过滤异常点切后台后轨迹中断系统省电策略杀掉定位进程使用后台定位模式并引导用户在系统设置中允许后台运行这里想多说一句“飞点”的问题。我最早做原型的时候没有做任何过滤测试时跑了一圈地图上两条轨迹叠加直接画出一个“回形针”。后来在定位回调里加了距离阈值和速度判断情况才好转。速度判断的思路是两点之间的距离除以时间差如果瞬时速度超过 10 米/秒那这个点大概率是漂移点直接丢弃。4.2 审核与隐私合规跑步小程序涉及地理位置信息微信审核对隐私的要求很严格。上线前必须在 mp 后台配置“用户隐私保护指引”把位置信息、微信昵称头像等用途写清楚。这里有一个很容易踩的坑如果你用的是 getPhoneNumber 这类能力也需要在隐私保护指引里声明不然调用时会直接被拦截。另外如果你的小程序里嵌了 H5 页面要注意 H5 顶部的导航栏表现。很多跑步应用会在小程序里内嵌活动页、报名页但 H5 页面的工具栏返回箭头有时会消失这种情况通常和 web-view 的页面栈有关需要在 H5 页面里检查自己是否调用了隐藏导航栏的接口或者通过 url 参数控制导航栏的显示状态。4.3 真机调试与环境问题真机调试时最常遇到的一个问题就是代码在开发者工具里跑得好好的一发到手机上就白屏或者接口报错。如果是云开发项目先检查云环境 ID 是否配置正确本地调试和线上环境的云环境 ID 很可能是两个不同的值。另外一个常见场景是你拿别人的源码在 HBuilder 里打开然后想在微信开发者工具里运行结果提示“不是开发者”或者“无法识别项目”。这个大概率是因为你打开的目录不是微信小程序的根目录或者项目本身是 uni-app 项目需要先在 HBuilder 里运行到微信开发者工具而不是直接拿源码目录去微信开发者工具里打开。运动类小程序还有一个细节不同手机的后台策略差异很大尤其是安卓阵营很多手机默认会杀掉长时间后台定位的进程。应对方案是在代码里监听切后台事件提示用户到系统设置里允许应用后台运行。虽然体验上有点打扰但这是目前最有效的兜底方案。5. 写在最后的一点个人体会做跑步类小程序这几年我最大的感受是定位和轨迹记录的代码框架并不复杂真正花时间的全在细节处理上。GPS 数据怎么去噪、后台定位怎么保证续航和轨迹完整、数据量大了之后怎么存储和绘制不卡顿这些才是让一个源码从“能跑”变成“能上线”的关键。如果你现在正在参考某个跑步小程序源码建议拿到手之后先不改功能原样在真机上跑一遍。跑的过程中细细观察定位的准确度、暂停和恢复的响应速度、跑完后的数据展示然后再考虑怎么优化。源码是很好的起点但只有把它拆开、弄懂、改过它才能真正变成你自己的东西。最后再分享一个小技巧运动结束后的轨迹保存别忘了把时间戳和时区一起存下来不要只存日期字符串。等你要做周报、月报这类累计统计的时候时区问题会省掉你很多返工的麻烦。本文还有配套的精品资源点击获取