vue2+UniApp微信小程序集成高德地图

技术文章大纲:UniApp微信小程序引入高德地图

准备工作

开发指南https://lbs.amap.com/api/wx/gettingstarted

  • 注册高德地图开发者账号并申请小程序应用的Key
  • 确保UniApp项目已配置微信小程序平台支持
  • 了解微信小程序与高德地图API的兼容性限制

高德地图SDK引入

  • 下载高德地图微信小程序JavaScript SDK

  • https://lbs.amap.com/api/wx/download

  • 将SDK文件放置于UniApp项目静态资源目录

  • const amapFile = require('@/libs/amap-wx.130.js')

基础地图功能实现

  • 在页面中声明map组件,使用的是uniapp的map组件
  • https://uniapp.dcloud.net.cn/component/map.html#map
  • 注:因为地图服务商问题,引入高德地图api但是显示是腾讯地图
  • 模板中嵌入地图组件并设置初始经纬度
  • 通过CSS调整地图容器样式与尺寸
javascript 复制代码
<template>
	<view class="map-location-component">
		<view class="map-container">
			<view class="search-bar">
				地址:<u-input v-model="searchKeyword" placeholder="请输入地址关键词搜索" 
				@input="handleSearch" class="search-input" clearable shape="circle"></u-input>
				
			</view>
			<view v-if="poiList.length > 0" class="poi-list">
				<view v-for="poi in poiList" :key="poi.id" class="poi-item" @click="selectPoi(poi)">
					<view class="poi-content">
						<view class="poi-name">{{ poi.name }}</view>
						<view class="poi-address">{{ poi.address }}</view>
					</view>
				</view>
			</view>
			<!-- 地图容器 -->
			<map id="amap-container" class="amap-container" :longitude="longitude" :latitude="latitude"
				:markers="markers" :scale="16" @tap="handleMapClick" show-location></map>
		</view>
	</view>
</template>

<script>
	const amapFile = require('@/libs/amap-wx.130.js')
	export default {
		name: 'MapLocation',
		data() {
			return {
				searchKeyword: '',
				searchLoading: false,
				locationLoading: false,
				poiList: [],
				longitude: '',
				latitude: '',
				markers: [],
				selectedLocation: null,
				searchTimer: null,
				amapKey: '地图key'
			}
		},
		mounted() {
			this.initMap()
		},
		methods: {
			//初始化位置
			setInitialLocation(coordinates, address) {
				if (!this.amap) {
					this.initMap()
				}
				if (coordinates && address) {
					const [lng, lat] = coordinates.split(',').map(Number)
					this.longitude = lng
					this.latitude = lat
					this.selectedLocation = {
						coordinates,
						address
					}
					this.searchKeyword = address
					this.markers = [{
						id: 1,
						longitude: lng,
						latitude: lat,
						title: address,
						width: 30,
						height: 30
					}]
					this.confirmSelection()
				}
			},
			confirmSelection() {
				if (this.selectedLocation) {
					this.$emit('confirm', this.selectedLocation)
				}
			},
			// 初始化地图
			initMap() {
				if (!this.amap) {
					this.amap = new amapFile.AMapWX({
						key: this.amapKey
					})
				}
			},
			// 获取当前位置
			getCurrentLocation() {
				uni.showLoading({
					title: '定位中...'
				})
				this.amap.getRegeo({
					success: (res) => {
						uni.hideLoading()
						const {
							longitude,
							latitude
						} = res[0]
						const address = res[0].name || res[0].desc
						this.longitude = longitude
						this.latitude = latitude
						const locationStr = `${longitude},${latitude}`
						this.markers = [{
							id: 1,
							longitude,
							latitude,
							title: address,
							width: 30,
							height: 30
						}]
						this.searchKeyword = address
						this.selectedLocation = {
							coordinates: locationStr,
							address: address
						};
						this.confirmSelection()
					},
					fail: (err) => {
						uni.hideLoading()
						uni.showToast({
							title: '定位失败',
							icon: 'none'
						})
						console.error('定位失败:', err)
					}
				})
			},
			// 搜索地址
			handleSearch() {
				if (!this.searchKeyword.trim()) {
					this.poiList = []
					return
				}
				clearTimeout(this.searchTimer)
				this.searchTimer = setTimeout(() => {
					this.amap.getInputtips({
						keywords: this.searchKeyword,
						city: '',
						success: (res) => {
							this.poiList = res.tips.filter(item => item.location)
						},
						fail: () => {
							uni.showToast({
								title: '搜索失败',
								icon: 'none'
							})
						}
					})
				}, 500)
			},
			selectPoi(item) {
				const address = item.name
				this.searchKeyword = address
				const [lng, lat] = item.location.split(',').map(Number)
				const locationStr = `${lng},${lat}`
				this.longitude = lng
				this.latitude = lat
				this.markers = [{
					id: 1,
					longitude: lng,
					latitude: lat,
					title: address,
					width: 30,
					height: 30
				}]
				this.poiList = []
				this.selectedLocation = {
					coordinates: locationStr,
					address: address
				};
				this.confirmSelection()
			},

			handleMapClick(e) {
				const lng = e.detail.longitude
				const lat = e.detail.latitude
				this.getAddressByLocation(lng, lat)
			},
			getAddressByLocation(lng, lat) {
				this.amap.getRegeo({
					location: `${lng},${lat}`,
					success: (res) => {
						const lng = res[0].longitude
						const lat = res[0].latitude
						const locationStr = `${lng},${lat}`
						const address = res[0].regeocodeData.formatted_address
						this.searchKeyword = address
						this.markers = [{
							id: 1,
							longitude: lng,
							latitude: lat,
							title: address,
							width: 30,
							height: 30,
						}];
						this.selectedLocation = {
							coordinates: locationStr,
							address: address
						};
						this.confirmSelection()
					}
				})
			}
		}
	}
</script>

<style scoped>
	.map-location-component {
		/* padding: 16rpx; */
		box-sizing: border-box;
	}

	.map-container {
		width: 100%;
	}

	.search-bar {
		display: flex;
		align-items: center;
		margin-bottom: 20rpx;
		position: relative;
	}

	.search-input {
		flex: 1;
		padding: 0 20rpx;
		border: 1px solid #dcdfe6;
		border-radius: 40rpx;
		font-size: 28rpx;
	}

	.clear-btn {
		position: absolute;
		right: 20rpx;
		width: 50rpx;
		height: 50rpx;
		line-height: 50rpx;
		text-align: center;
		font-size: 36rpx;
		color: #999;
		background: transparent;
		padding: 0;
	}

	.poi-list {
		max-height: 400rpx;
		overflow-y: auto;
		border: 1px solid #ebeef5;
		border-radius: 16rpx;
		margin-bottom: 20rpx;
	}

	.poi-item {
		padding: 20rpx;
		border-bottom: 1px solid #f5f5f5;
		cursor: pointer;
	}

	.poi-item:last-child {
		border-bottom: none;
	}

	.poi-item:active {
		background-color: #f5f7fa;
	}

	.poi-name {
		font-weight: bold;
		color: #303133;
		font-size: 30rpx;
		margin-bottom: 8rpx;
	}

	.poi-address {
		font-size: 26rpx;
		color: #606266;
	}

	.amap-container {
		width: 100%;
		height: 600rpx;
		border-radius: 16rpx;
		margin-bottom: 20rpx;
	}

	.btn-group {
		display: flex;
		gap: 20rpx;
	}

	.get-location-btn,
	.confirm-btn {
		flex: 1;
		height: 88rpx;
		line-height: 88rpx;
		font-size: 30rpx;
		border-radius: 16rpx;
	}

	.get-location-btn {
		background-color: #f5f7fa;
		color: #303133;
	}

	.confirm-btn {
		background-color: #007aff;
		color: #fff;
	}

	.confirm-btn:disabled {
		background-color: #b3d4fc;
	}
</style>

引入:

javascript 复制代码
<template>
  <MapLocation @confirm="handleLocationConfirm" ref="mapLocation"></MapLocation>
</template>
<script>
import MapLocation from "@/components/MapLocation.vue";
export default{
components: {
    MapLocation
  },
}
</script>

需要引入地图的方法里调用定位到当前位置:this.$refs.mapLocation.getCurrentLocation();

已有经纬度坐标和位置调用定位到已有位置:this.$refs.mapLocation.setInitialLocation(lng, lat); // lng:经度 lat:纬度

地图交互功能扩展

  • 监听地图缩放、拖动等事件
  • 添加标记点并实现点击弹窗
  • 集成位置搜索与路线规划功能

性能优化与注意事项

  • 控制地图渲染频率避免性能损耗
  • 处理微信小程序与H5环境差异
  • 遵守高德地图API调用频次限制

调试与发布

  • 使用真机调试解决API权限问题
  • 配置合法域名白名单
  • 提交微信小程序审核时的地图相关注意事项

更多功能,查看官方文档添加相关控件https://uniapp.dcloud.net.cn/component/map.html#map

相关推荐
小小王app小程序开发1 天前
淘宝扭蛋机小程序核心玩法拆解与技术运营分析
大数据·小程序
说私域1 天前
AI智能名片商城小程序数据清洗的持续运营策略与实践研究
大数据·人工智能·小程序·流量运营·私域运营
东东5161 天前
xxx食堂移动预约点餐系统 (springboot+微信小程序)
spring boot·微信小程序·小程序·毕业设计·个人开发·毕设
CHU7290351 天前
一番赏盲盒抽卡机小程序:解锁惊喜体验与社交乐趣的多元功能设计
前端·小程序·php
Rysxt_1 天前
UniApp五大UI框架与uni-ui核心区别对比
uni-app·uni-ui
2501_915918411 天前
HTTPS 代理失效,启用双向认证(mTLS)的 iOS 应用网络怎么抓包调试
android·网络·ios·小程序·https·uni-app·iphone
数字游民95271 天前
半年时间大概上了70个web站和小程序,累计提示词超过20w
人工智能·ai·小程序·vibecoding·数字游民9527
说私域1 天前
微商企业未来迭代的核心方向与多元探索——以链动2+1模式AI智能名片商城小程序为核心支撑
大数据·人工智能·小程序·流量运营·私域运营
27669582921 天前
美团 小程序 mtgsig
python·小程序·node·js·mtgsig1.2·美团小程序·大众点评小程序
2501_915106321 天前
混合应用(Hybrid)安全加固,不依赖源码对成品 IPA 混淆
android·安全·小程序·https·uni-app·iphone·webview