本文目录导读:

- 方案一:基于手动输入(最通用,适合任何运动)
- 方案二:使用浏览器
Geolocation API(前端 JS,实时 GPS) - 方案三:Python 处理 GPX/FIT 文件(分析运动记录)
- 方案四:硬件+传感器数据(最底层,如ESP32+GPS模块)
- 总结:哪个适合你?
针对“统计运动时长和距离”这一需求,脚本的实现方式取决于数据来源(GPS传感器、加速度计、手动输入或第三方API)。
以下是几种常见的脚本实现方案,涵盖前端(浏览器)、后端(Python) 以及可穿戴设备的场景。
基于手动输入(最通用,适合任何运动)
如果你的数据是用户手动输入的(比如在网页或App表单里填写开始/结束时间、跑的距离),脚本逻辑非常简单。
Python 脚本示例:
from datetime import datetime
def calculate_running_stats(start_time_str, end_time_str, distance_km):
# 输入格式: "2023-10-27 08:00:00"
start = datetime.strptime(start_time_str, "%Y-%m-%d %H:%M:%S")
end = datetime.strptime(end_time_str, "%Y-%m-%d %H:%M:%S")
duration_seconds = (end - start).total_seconds()
duration_minutes = duration_seconds / 60
duration_hours = duration_seconds / 3600
# 计算配速(分钟/公里)
if distance_km > 0:
pace = duration_minutes / distance_km
pace_str = f"{int(pace // 60)}分{int(pace % 60)}秒/公里"
else:
pace_str = "无"
speed_kmh = distance_km / duration_hours if duration_hours > 0 else 0
print(f"运动时长: {int(duration_hours)}小时{int(duration_minutes % 60)}分钟")
print(f"运动距离: {distance_km:.2f} 公里")
print(f"平均配速: {pace_str}")
print(f"平均速度: {speed_kmh:.2f} 公里/小时")
# 使用
calculate_running_stats("2023-10-27 08:00:00", "2023-10-27 09:25:00", 10.5)
使用浏览器 Geolocation API(前端 JS,实时 GPS)
这是最贴近“自动统计距离” 的方式,利用手机/电脑的 GPS 每几秒获取位置,累加两点间的距离。
HTML + JavaScript 脚本:
<!DOCTYPE html>
<html>
<body>
<button onclick="startTracking()">开始运动</button>
<button onclick="stopTracking()">结束运动</button>
<p>距离: <span id="distance">0</span> 米</p>
<p>时长: <span id="duration">0</span> 秒</p>
<script>
let watchId = null;
let startTime = null;
let totalDistance = 0; // 米
let lastPosition = null;
// 计算两点之间的距离 (Haversine公式)
function calcDistance(lat1, lon1, lat2, lon2) {
const R = 6371000; // 地球半径(米)
const dLat = (lat2 - lat1) * Math.PI / 180;
const dLon = (lon2 - lon1) * Math.PI / 180;
const a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
Math.sin(dLon/2) * Math.sin(dLon/2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
return R * c;
}
function updatePosition(position) {
if (lastPosition) {
const dist = calcDistance(
lastPosition.coords.latitude, lastPosition.coords.longitude,
position.coords.latitude, position.coords.longitude
);
// 过滤噪声 (GPS误差,小于1米的不算)
if (dist > 1) {
totalDistance += dist;
document.getElementById('distance').textContent = totalDistance.toFixed(1);
}
}
lastPosition = position;
// 更新时长
if (startTime) {
const elapsed = Math.floor((Date.now() - startTime) / 1000);
document.getElementById('duration').textContent = elapsed;
}
}
function handleError(error) {
console.error('GPS错误:', error.message);
}
function startTracking() {
startTime = Date.now();
totalDistance = 0;
lastPosition = null;
if ("geolocation" in navigator) {
watchId = navigator.geolocation.watchPosition(updatePosition, handleError, {
enableHighAccuracy: true, // 使用GPS
maximumAge: 1000, // 缓存1秒
timeout: 5000 // 超时5秒
});
} else {
alert("您的浏览器不支持GPS");
}
}
function stopTracking() {
if (watchId) {
navigator.geolocation.clearWatch(watchId);
watchId = null;
}
alert(`运动结束!总距离: ${totalDistance.toFixed(1)} 米`);
}
</script>
</body>
</html>
特点:
- 实时更新,不需要服务器。
- 注意:需要在 HTTPS 下运行,手机浏览器在后台可能暂停更新。
Python 处理 GPX/FIT 文件(分析运动记录)
很多运动手表(Garmin、Apple Watch)可以导出 GPX 或 FIT 文件,可以用 Python 解析这些文件来复盘运动。
Python 解析 GPX 文件 (使用 gpxpy 库):
pip install gpxpy
脚本:
import gpxpy
from datetime import datetime
def analyze_gpx(gpx_file_path):
with open(gpx_file_path, 'r') as f:
gpx = gpxpy.parse(f)
total_distance = 0 # 米
total_time = 0 # 秒
track = gpx.tracks[0]
segment = track.segments[0]
points = segment.points
# 总距离 (通过点与点累加)
for i in range(1, len(points)):
total_distance += points[i-1].distance_2d(points[i])
# 总时长 (第一个点和最后一个点的时间戳差)
if points[0].time and points[-1].time:
total_time = (points[-1].time - points[0].time).total_seconds()
# 计算平均配速 vs 速度
avg_speed_kmh = (total_distance / 1000) / (total_time / 3600) if total_time > 0 else 0
print(f"总距离: {total_distance / 1000:.2f} 公里")
print(f"运动时长: {total_time // 3600:.0f}小时{(total_time % 3600) // 60:.0f}分钟")
print(f"平均速度: {avg_speed_kmh:.2f} 公里/小时")
analyze_gpx("my_run.gpx")
硬件+传感器数据(最底层,如ESP32+GPS模块)
如果你是在做硬件开发(Arduino/ESP32),可以通过读取 GPS 模块(如 NEO-6M)的 NMEA 数据包来计算。
伪代码逻辑:
每1秒读取一次GPS坐标 (NMEA $GPGGA 或 $GPRMC 语句)
有fix并且位置有效:
这是第一个点:
存储为 last_lat, last_lon
否则:
计算 last_lat,last_lon 到 当前lat,lon 的距离 (Haversine)
累加 distance += 该段距离
更新 last_lat, last_lon
运动时长 = 当前时间 - 开始时间 (系统计时器)
哪个适合你?
| 场景 | 推荐方案 | 语言/工具 |
|---|---|---|
| 网页/App 实时记录 | 方案二 (Geolocation API) | JavaScript |
| 复盘手表/手机数据 | 方案三 (GPX解析) | Python + gpxpy |
| 简单手动计算 | 方案一 (手动输入) | Python / 任何语言 |
| 硬件DIY手环 | 方案四 (读取GPS模块) | C++ (Arduino) / MicroPython |
建议: 如果是做小程序或网页,直接使用 Geolocation API 是最快的,如果需要对运动效果进行大数据分析,推荐将数据导出为 GPX 后用 Python 处理。