uniapp 微信小程序 选择地图位置并返回经纬度及详细地址(uni.chooseLocation和高德地图api两种方式实现)

47 篇文章 0 订阅

uniapp 微信小程序实现选择地图位置功能

最近在做商家小程序,就是用于给实体店老板进行网上开店的小程序。
其中有一项功能就是获取商店的位置,要求支持:获取当前定位/检索到指定位置/地图选点等功能,并返回选择地点的regionId和经纬度以及详细的地址等信息。

获取地理信息的授权功能

在这里插入图片描述

1. manifest.json中写入授权地理位置的描述

在这里插入图片描述
代码如下:

"permission" : {
   "scope.userLocation" : {
        "desc" : "您的位置将用于绑定您的区域"
    }
},

2. 点击地图图标时,调用下面的代码实现授权(uni.chooseLocation方式)

注意:调取授权地理位置,需要用到uni的api,下面的三个方法都是可以的。
uni.getLocation uni.chooseLocation uni.openLocation

在这里插入图片描述

getMapLocation(){
	uni.chooseLocation({
		success:(res)=> {
			console.log(res);
			// this.getRegionFn(res);
		},
		fail:()=>{
			// 如果用uni.chooseLocation没有获取到地理位置,则需要获取当前的授权信息,判断是否有地理授权信息
			uni.getSetting({
				success: (res) => {
					console.log(res);
					var status = res.authSetting;
					if(!status['scope.userLocation']){
					// 如果授权信息中没有地理位置的授权,则需要弹窗提示用户需要授权地理信息
						uni.showModal({
							title:"是否授权当前位置",
							content:"需要获取您的地理位置,请确认授权,否则地图功能将无法使用",
							success:(tip)=>{
								if(tip.confirm){
								// 如果用户同意授权地理信息,则打开授权设置页面,判断用户的操作
									uni.openSetting({
										success:(data)=>{
										// 如果用户授权了地理信息在,则提示授权成功
											if(data.authSetting['scope.userLocation']===true){
												uni.showToast({
													title:"授权成功",
													icon:"success",
													duration:1000
												})
												// 授权成功后,然后再次chooseLocation获取信息
												uni.chooseLocation({
													success: (res) => {
														console.log("详细地址",res);
														// this.getRegionFn(res);
													}
												})
											}else{
												uni.showToast({
													title:"授权失败",
													icon:"none",
													duration:1000
												})
											}
										}
									})
								}
							}
						})
					}
				},
				fail: (res) => {
					uni.showToast({
						title:"调用授权窗口失败",
						icon:"none",
						duration:1000
					})
				}
			})
		}
	});
},

在这里插入图片描述
授权成功后,就可以进入到uniapp自带的选择地点的页面了,可以直接选取/拖动地图选取/搜索地点选取等多种方式实现地点的选择,页面真的是很好看啊。完全长在了我的审美点上。哈哈。

唯一的缺点就是,这个默认使用的腾讯地图,但是腾讯地图检索不是很精确,不如高德。

下面介绍高德地图的使用方式

3. 使用高德地图api调取地图并实现选取地点的功能

代码如下:

getMapLocation0(){
	uni.getLocation({
	    type: 'wgs84',
	    success: (res)=>{
			if(this.formData2.longitude && this.formData2.latitude){
				uni.navigateTo({
					url:"/pages/user/map?lng="+this.formData2.longitude+"&lat="+this.formData2.latitude
				})
			}else{
				uni.navigateTo({
					url:"/pages/user/map?lng="+res.longitude+"&lat="+res.latitude
				})
			}
	    },
		fail:()=>{
			uni.getSetting({
				success: (res) => {
					console.log(res);
					var status = res.authSetting;
					if(!status['scope.userLocation']){
						uni.showModal({
							title:"是否授权当前位置",
							content:"需要获取您的地理位置,请确认授权,否则地图功能将无法使用",
							success:(tip)=>{
								if(tip.confirm){
									uni.openSetting({
										success:(data)=>{
											if(data.authSetting['scope.userLocation']===true){
												uni.showToast({
													title:"授权成功",
													icon:"success",
													duration:1000
												})
												uni.getLocation({
												    type: 'wgs84',
												    success: (res)=>{
												        console.log('当前位置的经度:' + res.longitude);
												        console.log('当前位置的纬度:' + res.latitude);
														uni.navigateTo({
															url:"/pages/user/map?lng="+res.longitude+"&lat="+res.latitude
														})
												    }
												})
											}else{
												uni.showToast({
													title:"授权失败",
													icon:"none",
													duration:1000
												})
											}
										}
									})
								}
							}
						})
					}else{
						uni.getLocation({
						    type: 'wgs84',
						    success: (res)=>{
						        console.log('当前位置的经度:' + res.longitude);
						        console.log('当前位置的纬度:' + res.latitude);
								uni.navigateTo({
									url:"/pages/user/map?lng="+res.longitude+"&lat="+res.latitude
								})
						    }
						})
					}
				},
				fail: (res) => {
					uni.showToast({
						title:"调用授权窗口失败",
						icon:"none",
						duration:1000
					})
				}
			})
		}
	})
},

/pages/user/map页面布局及代码如下:

<template>
	<view class="content">
		<view class="btns"> // 选取地点后的确定和取消按钮
			<view @click="back">取消</view>
			<view @click="checkAdd">确定</view>
		</view>
		// 地图部分
		 <map style="width: 100%; height: 60vh;" :latitude="latitude" :longitude="longitude" :markers="markers" @tap="tap" :include-points="markers" :scale="10"/>
		 <!-- <view id="container"></view> -->
		 // 搜索框
		 <view class="inputCon">
			 <view class="searchView">
				 <text class="iconfont icon-sousuo"></text>
				 <input type="text" placeholder="搜索地点" v-model="searchWords" confirm-type="search" @confirm="searchFn"/>
				 <text @click="cancel">取消</text>
			 </view>
		 </view>
		 // 地点列表部分
		 <view class="list">
			 <view class="item" v-for="(add,index) in dataTips" :key="add.id" @click="select(add,index)"
			 :class="selectIndex==index?'active':''">
				 <view class="name">{{add.name}}</view>
				 <view class="address">{{add.district || ''}}{{add.address || ''}}</view>
			 </view>
		 </view>
	</view>
</template>

<script>
// 引入高德地图api提供的微信小程序的接口
	var amapFile = require('@/utils/ossutil/amap-wx.js');//如:..-/..-/libs/amap-wx.js
	// 创建地图
	var myAmapFun = new amapFile.AMapWX({key: 'e4ee780c241c1874496e21efa14c2562'});
	console.log("创建了高德地图");
	export default{
		data(){
			return{
				selectIndex:undefined,
				selectAddr:{},
				searchWords:"",
				id:0, // 使用 marker点击事件 需要填写id
				title: 'map',
				latitude: 39.909,
				longitude: 116.39742,
				markers: [{
					latitude: 39.909,
					longitude: 116.39742,
					width:30,
					height:30,
					iconPath: '../../static/ditu.png'
				}],
				dataTips:[]
			}
		},
		onLoad(options) {
			if(options && options.lng){
				this.longitude = options.lng;
				this.markers[0].longitude = this.longitude;
			}
			if(options && options.lat){
				this.latitude = options.lat;
				this.markers[0].latitude = this.latitude;
			}
			// 获取当前位置的地点列表
			myAmapFun.getPoiAround({
			  success: (data)=>{
				console.log("获取当前的列表",data);
				this.dataTips = data.poisData;
			  },
			  fail: (info)=>{
				console.log(info)
			  }
			})
		},
		methods:{
			// 选择地点后,将选取的地点传递到前一个页面中
			checkAdd(){
				console.log(this.markers);
				uni.setStorageSync('address', this.markers[0]);
				var pages = getCurrentPages();// 获取所有的页面栈
				var prevPage = pages[pages.length - 2]; // 找到上一个页面,注意是页面,如果是页面中有组件,则需要通过页面接受到数据后,再次往组件中传递
				prevPage.$vm.addressObj = this.selectAddr;//在上一个页面中就可以用addressObj进行接收
				uni.navigateBack();
			},
			back(){
				uni.navigateBack();
			},
			cancel(){
				if(this.searchWords){
					this.searchWords = "";
					myAmapFun.getPoiAround({
					  location: this.markers[0].longitude+','+this.markers[0].latitude,
					  success: (data)=>{
						console.log("获取当前的列表",data);
						this.dataTips = data.poisData;
					  },
					  fail: (info)=>{
						console.log(info)
					  }
					})
				}
			},
			reserGeo(){
				myAmapFun.getRegeo({
				  success: (data)=>{
					console.log("获取当前定位信息",data);
				  },
				  fail: (info)=>{
					console.log(info)
				  }
				})
			},
			// 根据地址列表中选择某一个地点
			select(add,index){
				console.log(add);
				if(!add){
					return;
				}
				this.selectIndex = index;
				var location = add.location.split(",");
				console.log(location);
				this.selectAddr = {
					address:add.pname?(add.pname+add.cityname+add.adname+add.address):(add.district+add.address),
					latitude:location[1],
					longitude:location[0]
				};
				this.markers[0].latitude = +location[1];
				this.markers[0].longitude = +location[0];
			},
			// 在地图上点击进行选点,这个选点在地图缩放比例较大时无效,因为精读的问题。
			tap(e){
				console.log(e);
				var location = e.detail.longitude +','+e.detail.latitude
				myAmapFun.getRegeo({
				  location: location,
				  success: (data)=>{
					console.log("获取指定定位信息",data);
					this.selectAddr = {
						address:data[0].regeocodeData.formatted_address,
						latitude:e.detail.latitude,
						longitude:e.detail.longitude
					};
					this.markers[0].latitude = data[0].latitude;
					this.markers[0].longitude = data[0].longitude;
					myAmapFun.getPoiAround({
					  location: data[0].longitude+','+data[0].latitude,
					  success: (data)=>{
						console.log("获取当前的列表",data);
						this.dataTips = data.poisData;
					  },
					  fail: (info)=>{
						console.log(info)
					  }
					})
				  },
				  fail: (info)=>{
					console.log(info);
				  }
				})
			},
			// 根据内容进行检索
			searchFn(){
				console.log("根据地址检索",this.searchWords);
				myAmapFun.getInputtips({
				  keywords: this.searchWords,
				  location: '',
				  success: (data) => {
					  console.log(111,data);
					if(data && data.tips){
					  this.dataTips = data.tips;
					}
				  },
				  fail:data=>{
					  console.log(222,data);
				  }
				})
			}
		}
	}
</script>

<style lang="scss" scoped>
	.btns{
		position: fixed;
		top:0;
		left:0;
		height:260upx;
		width:100%;
		background:linear-gradient(to bottom,rgba(0,0,0,0.4),rgba(0,0,0,0));
		display: flex;
		align-items: center;
		justify-content: space-between;
		z-index:10 !important;
		view{
			margin:100upx 24upx 0;
			font-size:30upx;
			&:first-child{
				color:#fff;
			}
			&:last-child{
				width:100upx;
				height:60upx;
				line-height: 60upx;
				text-align: center;
				border-radius: 10upx;
				background:#E13500;
				color:#fff;
			}
		}
	}
	.content{
		.list{
			height:calc(40vh - 100upx);
			overflow-y: auto;
			width:702upx;
			margin:-40upx auto 0;
			padding-bottom:20upx;
			.item{
				border-bottom:2upx solid #f3f3f3;
				&:last-child{
					border:none;
				}
				.address{
					font-size:22upx;
					color:#666;
					margin:10upx 0;
				}
				.name{
					font-size:30upx;
					color:#333;
					margin-top:10upx;
				}
				&.active{
					.name{
						font-weight: bold;
						color:#E13500;
					}
					.address{
						color:#E13500;
					}
				}
			}
		}
		.inputCon{
			width:100%;
			background:#fff;
			top:-60upx;
			position: relative;
			z-index:20;
			height:100upx;
			display: flex;
			align-items: center;
			justify-content: center;
			.searchView{
				width:702upx;
				height:60upx;
				display: flex;
				align-items: center;
				line-height: 60upx;
				border-radius: 40upx;
				padding:0 30upx;
				box-sizing: border-box;
				background:#f3f3f3;
				font-size:26upx;
				.iconfont{
					color:#666;
					margin-right:20upx;
				}
				input{
					flex:1;
				}
				view{
					flex-shrink: 0;
				}
			}
		}
		
	}
</style>

最终实现效果页面如下:
在这里插入图片描述
uniapp 中的map组件,在微信小程序中,右下角是自带腾讯地图几个字的,为了能够去掉,我想到了一个办法,就是将下面的搜索框和地址列表上移动,盖住腾讯地图几个字。完成。

  • 3
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值