uni-app地图定位踩坑记:地图功能和定位的那些坑 0 次阅读

在uni-app开发中,地图和定位功能经常会遇到各种问题。本文总结了一些常见的坑和解决方案,帮助大家更好地实现地图相关功能。

1. 定位权限问题

1.1 获取定位权限

问题描述:
用户拒绝定位权限后,无法正常使用定位功能。

解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 检查定位权限
async checkLocationAuth() {
try {
const res = await uni.getSetting()
if (!res.authSetting['scope.userLocation']) {
// 未授权,引导用户开启
await uni.showModal({
title: '提示',
content: '需要获取您的位置信息,是否授权?',
success: async (res) => {
if (res.confirm) {
await uni.openSetting()
}
}
})
}
return res.authSetting['scope.userLocation']
} catch (e) {
console.error('获取权限失败:', e)
return false
}
}

1.2 定位失败处理

问题描述:
定位失败时没有合适的提示和处理。

解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// 获取位置信息
async getLocation() {
try {
const auth = await this.checkLocationAuth()
if (!auth) {
uni.showToast({
title: '请先开启定位权限',
icon: 'none'
})
return null
}

const location = await uni.getLocation({
type: 'gcj02', // gcj02火星坐标系
isHighAccuracy: true, // 开启高精度定位
highAccuracyExpireTime: 3000 // 超时时间
})

return location
} catch (e) {
let message = '定位失败'
switch (e.errMsg) {
case 'getLocation:fail system permission denied':
message = '系统定位权限已关闭'
break
case 'getLocation:fail timeout':
message = '定位超时,请重试'
break
default:
message = '定位失败,请检查网络'
}

uni.showToast({
title: message,
icon: 'none'
})
return null
}
}

2. 地图显示问题

2.1 地图加载失败

问题描述:
地图组件加载失败或显示空白。

解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<!-- 地图组件使用 -->
<template>
<view class="map-container">
<map
id="map"
:style="mapStyle"
:latitude="latitude"
:longitude="longitude"
:markers="markers"
:scale="scale"
@regionchange="onRegionChange"
@markertap="onMarkerTap"
:show-location="true"
></map>
</view>
</template>

<script>
export default {
data() {
return {
mapStyle: 'width: 100%; height: 300px;',
latitude: 0,
longitude: 0,
markers: [],
scale: 16
}
},
async onReady() {
// 等待地图组件创建完成
this.mapContext = uni.createMapContext('map', this)
await this.initMap()
},
methods: {
async initMap() {
try {
const location = await this.getLocation()
if (location) {
this.latitude = location.latitude
this.longitude = location.longitude
// 添加当前位置标记
this.addMarker({
id: 0,
latitude: location.latitude,
longitude: location.longitude,
title: '当前位置'
})
}
} catch (e) {
console.error('初始化地图失败:', e)
}
}
}
}
</script>

2.2 标记点显示问题

问题描述:
自定义标记点样式不生效或显示异常。

解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 添加自定义标记
function addMarker(point) {
const marker = {
id: point.id,
latitude: point.latitude,
longitude: point.longitude,
title: point.title,
width: 32,
height: 32,
callout: {
content: point.title,
color: '#ffffff',
fontSize: 14,
borderRadius: 4,
bgColor: '#1989fa',
padding: 8,
display: 'ALWAYS'
},
// 自定义图标
iconPath: point.iconPath || '/static/images/marker.png',
// 自定义气泡
customCallout: {
display: 'ALWAYS',
anchorY: 0,
anchorX: 0
}
}

this.markers.push(marker)
}

3. 路线规划问题

3.1 路线绘制错误

问题描述:
路线规划时绘制的路线不准确或无法显示。

解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 规划路线
async planRoute(start, end) {
try {
// 清除旧路线
this.polyline = []

// 获取路线规划
const route = await this.getRoutePoints(start, end)
if (!route) return

// 绘制路线
this.polyline = [{
points: route,
color: '#1989fa',
width: 4,
arrowLine: true,
borderColor: '#ffffff',
borderWidth: 2
}]

// 调整视野以显示整条路线
this.mapContext.includePoints({
points: [start, end],
padding: [50, 50, 50, 50]
})
} catch (e) {
console.error('规划路线失败:', e)
}
}

3.2 导航问题

问题描述:
调用导航功能时出现兼容性问题。

解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// 打开导航
async openNavigation(destination) {
try {
// 检查平台
// #ifdef APP-PLUS
// APP端使用系统导航
plus.runtime.openURL(
`androidamap://navi?sourceApplication=appname&lat=${destination.latitude}&lon=${destination.longitude}&dev=0&style=2`
)
// #endif

// #ifdef H5
// H5端使用Web导航
window.location.href = `https://uri.amap.com/navigation?to=${destination.longitude},${destination.latitude}&mode=car&policy=1`
// #endif

// #ifdef MP-WEIXIN
// 小程序端使用微信导航
uni.openLocation({
latitude: destination.latitude,
longitude: destination.longitude,
name: destination.name,
address: destination.address
})
// #endif
} catch (e) {
uni.showToast({
title: '打开导航失败',
icon: 'none'
})
}
}

4. 性能优化问题

4.1 标记点过多

问题描述:
地图上标记点太多导致卡顿。

解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// 聚合标记点
function clusterMarkers(markers, distance = 20) {
const clusters = []
const used = new Set()

markers.forEach((marker, index) => {
if (used.has(index)) return

const cluster = {
center: {
latitude: marker.latitude,
longitude: marker.longitude
},
points: [marker]
}

// 查找附近的点
markers.forEach((m, i) => {
if (i === index || used.has(i)) return

const d = this.calculateDistance(
marker.latitude,
marker.longitude,
m.latitude,
m.longitude
)

if (d <= distance) {
cluster.points.push(m)
used.add(i)
}
})

clusters.push(cluster)
})

return clusters
}

4.2 频繁更新

问题描述:
频繁更新标记点位置导致性能问题。

解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 使用节流更新位置
const throttleUpdate = throttle(function(markers) {
this.markers = markers
}, 200)

// 更新标记位置
function updateMarkers(newMarkers) {
throttleUpdate(newMarkers)
}

// 节流函数
function throttle(fn, delay) {
let timer = null
return function(...args) {
if (timer) return
timer = setTimeout(() => {
fn.apply(this, args)
timer = null
}, delay)
}
}

5. 实用功能分享

5.1 计算距离

1
2
3
4
5
6
7
8
9
10
11
12
13
// 计算两点距离
function calculateDistance(lat1, lng1, lat2, lng2) {
const R = 6371 // 地球半径,单位km
const dLat = (lat2 - lat1) * Math.PI / 180
const dLng = (lng2 - lng1) * 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(dLng/2) * Math.sin(dLng/2)

const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a))
return R * c
}

5.2 地址解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 地址转坐标
async geocode(address) {
try {
const res = await uni.request({
url: 'geocode-api-url',
data: {
address: address,
key: 'your-api-key'
}
})

if (res.data.status === '1') {
return {
latitude: res.data.result.location.lat,
longitude: res.data.result.location.lng
}
}
return null
} catch (e) {
console.error('地址解析失败:', e)
return null
}
}

6. 最佳实践建议

  1. 注意权限处理
  2. 做好错误提示
  3. 优化性能表现
  4. 处理兼容问题
  5. 注意用户体验

7. 总结

  1. 权限问题要提前处理
  2. 地图显示要做好兼容
  3. 路线规划要考虑性能
  4. 导航功能要适配平台
  5. 注意优化用户体验

如果觉得文章对你有帮助,欢迎点赞、评论、分享,你的支持是我继续创作的动力!

上一篇 2024年AI编程助手深度评测:哪款最适合你?
下一篇 uni-app文件上传踩坑记:图片处理和上传全攻略
感谢您的支持!
微信赞赏码 微信赞赏
支付宝赞赏码 支付宝赞赏