下面是一个简单的微信小程序GPS测速功能的实现代码,包括前端页面和后端逻辑。
1. 页面结构 (index.wxml)
<view class="container">
<view class="speed-display">
<text class="speed-value">{{speed}}</text>
<text class="speed-unit">km/h</text>
</view>
<view class="info-section">
<view class="info-item">
<text>经度:</text>
<text>{{longitude}}</text>
</view>
<view class="info-item">
<text>纬度:</text>
<text>{{latitude}}</text>
</view>
<view class="info-item">
<text>精度:</text>
<text>{{accuracy}}米</text>
</view>
</view>
<button bindtap="startGPS" type="primary" disabled="{{isRunning}}">开始测速</button>
<button bindtap="stopGPS" type="warn" disabled="{{!isRunning}}">停止测速</button>
</view>
2. 页面样式 (index.wxss)
.container {
display: flex;
flex-direction: column;
align-items: center;
padding: 20px;
}
.speed-display {
display: flex;
align-items: baseline;
margin: 40px 0;
}
.speed-value {
font-size: 60px;
font-weight: bold;
}
.speed-unit {
font-size: 20px;
margin-left: 5px;
}
.info-section {
width: 100%;
margin: 30px 0;
}
.info-item {
display: flex;
justify-content: space-between;
margin: 10px 0;
padding: 10px;
background-color: #f5f5f5;
border-radius: 5px;
}
button {
width: 80%;
margin: 10px 0;
}
3. 页面逻辑 (index.js)
Page({
data: {
speed: '0.00',
longitude: '--',
latitude: '--',
accuracy: '--',
isRunning: false,
gpsWatchId: null,
lastPosition: null,
lastUpdateTime: null
},
startGPS: function() {
const that = this;
// 检查是否已经授权
wx.getSetting({
success(res) {
if (!res.authSetting['scope.userLocation']) {
// 未授权,请求授权
wx.authorize({
scope: 'scope.userLocation',
success() {
that._startWatching();
},
fail() {
wx.showToast({
title: '需要位置权限',
icon: 'none'
});
}
});
} else {
// 已授权,开始监听
that._startWatching();
}
}
});
},
_startWatching: function() {
const that = this;
this.setData({
isRunning: true,
speed: '0.00'
});
// 开始监听位置变化
const watchId = wx.startLocationUpdate({
type: 'gcj02',
success: () => {
wx.onLocationChange(function(res) {
that._updatePosition(res);
});
},
fail(err) {
console.error('启动位置监听失败', err);
wx.showToast({
title: '启动失败',
icon: 'none'
});
that.setData({ isRunning: false });
}
});
this.setData({ gpsWatchId: watchId });
},
_updatePosition: function(position) {
const now = Date.now();
let speed = 0;
if (this.data.lastPosition && this.data.lastUpdateTime) {
// 计算距离(米)
const distance = this._calculateDistance(
this.data.lastPosition.latitude,
this.data.lastPosition.longitude,
position.latitude,
position.longitude
);
// 计算时间差(小时)
const timeDiff = (now - this.data.lastUpdateTime) / 1000 / 3600;
// 计算速度(公里/小时)
if (timeDiff > 0) {
speed = distance / 1000 / timeDiff;
}
}
this.setData({
speed: speed.toFixed(2),
longitude: position.longitude.toFixed(6),
latitude: position.latitude.toFixed(6),
accuracy: position.accuracy.toFixed(0),
lastPosition: position,
lastUpdateTime: now
});
},
// 计算两个坐标点之间的距离(米)
_calculateDistance: function(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;
},
stopGPS: function() {
if (this.data.gpsWatchId) {
wx.stopLocationUpdate({
success: () => {
wx.offLocationChange();
this.setData({
isRunning: false,
gpsWatchId: null
});
},
fail(err) {
console.error('停止位置监听失败', err);
}
});
}
},
onUnload: function() {
// 页面卸载时停止监听
this.stopGPS();
}
});
4. 配置文件 (app.json)
确保在app.json中声明了位置权限:
{
"pages": [
"pages/index/index"
],
"permission": {
"scope.userLocation": {
"desc": "你的位置信息将用于测速功能"
}
},
"requiredPrivateInfos": ["getLocation", "onLocationChange", "startLocationUpdate"]
}