自动获取当前定位信息(经纬度和城市)兼容小程序和h5,技术栈uniapp+vue3+setup
·
需要用到第三方地图的逆解析,反推出当前城市。我这里用的是腾讯地图api,需要准备key
官网链接: 腾讯位置服务 - 立足生态,连接未来
注意:下面代码的地址链接 key 得换成你自己的key,别用我的,用我的你会报错。
例如:url: '/map-api/ws/geocoder/v1/?location=28.23529,112.93134&key=AVSBZ-6BILR-K2EWT-WCIAT-DBFFF-XXXXX&get_poi=1',
这里替换成你的key,总共有三个地方,请注意一下。
// 自动获取用户定位
export async function autoGetLocation() {
try {
// #ifdef MP-WEIXIN
// 检查定位权限
const authResult = await uni.getSetting()
if (!authResult.authSetting['scope.userLocation']) {
// 没有定位权限,请求权限
const authRes = await uni.authorize({
scope: 'scope.userLocation'
})
}
// #endif
// 获取定位
const location = await new Promise((resolve, reject) => {
uni.getLocation({
type: 'gcj02',
success: (res) => resolve(res),
fail: (err) => reject(err)
})
})
// 根据平台使用不同的逆地理编码方案
let cityName = await getCityByLocation(location.latitude, location.longitude);
return {
latitude: location.latitude,
longitude: location.longitude,
cityName
}
} catch (error) {
console.error('自动定位失败:', error)
uni.showToast({
title: "无法获取当前位置,请手动选择城市",
icon: "none",
duration: 3000
});
return {
latitude: '',
longitude: '',
cityname: ''
}
}
}
// 测试代理接口是否正常工作
async function testProxyConnection() {
try {
const response = await uni.request({
url: '/map-api/ws/geocoder/v1/?location=28.23529,112.93134&key=AVSBZ-6BILR-K2EWT-WCIAT-DBFFF-XXXXX&get_poi=1',
method: 'GET',
timeout: 5000
})
return true
} catch (error) {
return false
}
}
// 根据坐标获取城市信息
async function getCityByLocation(lat, lng) {
try {
// #ifdef H5
// H5环境:使用代理接口调用腾讯地图API
// 先测试代理连接
const proxyWorking = await testProxyConnection()
if (proxyWorking) {
try {
// 使用代理接口调用腾讯地图逆地理编码API
const response = await new Promise((resolve, reject) => {
uni.request({
url: `/map-api/ws/geocoder/v1/?location=${lat},${lng}&key=AVSBZ-6BILR-K2EWT-WCIAT-DBFFF-XXXXXX&get_poi=1`,
method: 'GET',
timeout: 10000,
success: (res) => resolve(res),
fail: (err) => reject(err)
})
})
if (response.data && response.data.status === 0 && response.data.result) {
const addressComponent = response.data.result.address_component
return addressComponent.city || addressComponent.district || '长沙市'
} else {
// 降级方案:使用坐标范围判断城市
return getCityByCoordinates(lat, lng)
}
} catch (error) {
console.error('H5代理定位失败:', error)
// 最终降级方案:使用坐标范围判断城市
return getCityByCoordinates(lat, lng)
}
} else {
// 代理不可用,直接使用坐标判断城市
return getCityByCoordinates(lat, lng)
}
// #endif
// #ifdef MP-WEIXIN
// 小程序环境:直接调用腾讯地图API
const response = await new Promise((resolve, reject) => {
uni.request({
url: `https://apis.map.qq.com/ws/geocoder/v1/?location=${lat},${lng}&key=AVSBZ-6BILR-K2EWT-WCIAT-DBFFF-XXXXX&get_poi=1`,
method: 'GET',
success: (res) => resolve(res),
fail: (err) => reject(err)
})
})
if (response.data && response.data.status === 0 && response.data.result) {
const addressComponent = response.data.result.address_component
// console.log('定位成功,当前城市:', addressComponent)
return addressComponent.city || addressComponent.district || '长沙市'
} else {
return '长沙市'
}
// #endif
} catch (error) {
console.error('获取城市信息失败:', error)
return '长沙市'
}
}
// 根据坐标判断城市(简单的地理范围判断)
const getCityByCoordinates = (lat, lng) => {
// 主要城市的经纬度范围(简化版)
const cityRanges = [{
name: '北京市',
latMin: 39.4,
latMax: 41.0,
lngMin: 115.7,
lngMax: 117.4
},
{
name: '上海市',
latMin: 30.7,
latMax: 31.9,
lngMin: 120.9,
lngMax: 122.1
},
{
name: '广州市',
latMin: 22.7,
latMax: 23.8,
lngMin: 113.0,
lngMax: 114.0
},
{
name: '深圳市',
latMin: 22.4,
latMax: 22.9,
lngMin: 113.7,
lngMax: 114.6
},
{
name: '杭州市',
latMin: 30.0,
latMax: 30.6,
lngMin: 119.8,
lngMax: 120.6
},
{
name: '长沙市',
latMin: 28.0,
latMax: 28.5,
lngMin: 112.8,
lngMax: 113.2
},
{
name: '武汉市',
latMin: 30.3,
latMax: 30.8,
lngMin: 114.0,
lngMax: 114.6
},
{
name: '成都市',
latMin: 30.4,
latMax: 30.9,
lngMin: 103.8,
lngMax: 104.3
}
]
for (const city of cityRanges) {
if (lat >= city.latMin && lat <= city.latMax &&
lng >= city.lngMin && lng <= city.lngMax) {
return city.name
}
}
// 默认返回长沙市
return '长沙市'
}
在使用第三方地图api,可能会造成跨域问题,所以需要配置代理
// 腾讯地图API代理
'/map-api': {
target: 'https://apis.map.qq.com',
changeOrigin: true,
rewrite: (p) => p.replace(/^\/map-api/, ''),
headers: {
'Referer': 'https://apis.map.qq.com',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
},
timeout: 10000,
configure: (proxy, options) => {
proxy.on('error', (err, req, res) => {
console.log('地图API代理错误:', err);
});
proxy.on('proxyReq', (proxyReq, req, res) => {
console.log('发送地图API请求:', req.url);
});
proxy.on('proxyRes', (proxyRes, req, res) => {
console.log('收到地图API响应:', proxyRes.statusCode);
});
}
}

还需要在 manifest.json 文件中进行配置
"mp-weixin": {
"permission": {
"scope.userLocation": {
"desc": "你的位置信息将用于小程序位置接口的效果展示"
}
},
"requiredPrivateInfos": ["chooseAddress", "getLocation", "chooseLocation"]
}

"h5": {
"permission": {
"geolocation": {
"description": "获取你的位置信息用于展示当前城市"
}
},
"sdkConfigs": {
"maps": {
"qqmap": {
"key": "AVSBZ-6BILR-K2EWT-WCIAT-DBFFF-XXXXT"
}
}
}
}

最后注意一下,如果没成功,你看下这里是否有这些内容,这些都是关于定位相关的,需要配置上

"<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_BACKGROUND_LOCATION\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_MOCK_LOCATION\"/>",
更多推荐


所有评论(0)