uniapp开发中遇到的Location相关应用

uniapp开发微信小程序和app里用到过的Location相关的应用

1.首先要获取位置uni.getLocation

getlocation(){
    uni.getLocation({
	    type: 'gcj02',
	    success: function (res) {
		    console.log('当前位置的经度:' + res.longitude);
		    console.log('当前位置的纬度:' + res.latitude);
	    }
    });
},


 默认为 wgs84 返回 gps 坐标,gcj02 返回国测局坐标,可用于 uni.openLocation 和 map 组件坐标,App 和 H5 需配置定位 SDK 信息才可支持 gcj02。

2.用经纬度,实现相关应用

        1>查看位置,在内置地图的显示 uni.openLocation

dotLocation(){//坐标点位置
	uni.openLocation({
		latitude: Number(34.605),
		longitude: Number(113.1),
		scale: 12,
		complete:function(res){
			console.log(res)
		}
	})
},

 我直接填了个经纬度,用的时候可以换成变量

 

 打开是这样,可以点右下角,去选择app导航

        2>打开内置地图查询位置uni.chooseLocation

chooselocation(){
    uni.chooseLocation({
	    success: function (res) {
		    console.log('位置名称:' + res.name);
		    console.log('详细地址:' + res.address);
		    console.log('纬度:' + res.latitude);
		    console.log('经度:' + res.longitude);
	    }
    });

}

 

样式和功能不能改变,如有别的需求可用map组件

3>map地图组件

这里是一个需求:1.类似uni.chooseLocation 2.电子围栏3.保留上次选的位置

<template>
	<view>
		<!-- 地图 :include-points="covers"-->
		<view class="body">

			<map :style="'width: 100%; height: '+mh*senceh+'px;'" :latitude="latitude" :longitude="longitude" :scale="isScale"
				@markertap="markertap" :markers="covers" :show-location="true" :polygons="polylines" @tap="selectpoint" id="map1" ref="map1" enable-zoom=true @regionchange="regionchange">
				 <!-- @touchmove="touchmove" -->
				<view class="" :style="'position:absolute;top:'+mtop+'px;left:'+mleft+'px;'">
					<image src="../../static/location@2x.png" style="width: 31px;height: 50px;" mode=""></image>
				</view>
			</map>

			<view class="btns" :style="'top:'+ mt +'px;'">
				<view class="cancle" @click="cancle">取消</view>
			</view>
			<!-- 搜索结果 -->
			<view class="result"  :style="'height:'+1-Number(mh)+';'">
				<!-- 定位icon -->
				<view class="end">
					<image src="../../static/dingweiback.png" class="ricon" mode="" @click="backcenter"></image>
				</view>
				<!-- 不透明 -->
				<view class="info" :style="'height: '+bh*senceh+'px;'">
					<!-- 搜索框 -->
					<view class="search">
						<view class="sinfo">
							<view class="input">
								<image class="icon" src="../../static/1_2_1_icon1@2x.png" mode=""></image>
								<input type="text" v-model="inputname" @focus="focus" @blur="blur" placeholder="关键词搜索"
									@input="search(inputname)" />
							</view>
							<view class="confirm" @click="confirmbtn">确定</view>
						</view>
					</view>
					<!-- 结果 -->
					<scroll-view v-if="!isfocus||(isfocus&&inputname)" scroll-y="true" class="scroll" @scroll="mov" :style="'height: '+sh*senceh+'px;'">
						
							<view class="item" v-for="item,index in resultpoint" :key="index" @click="selectresult(index)">
								<view class="">
									<view class="name">{{item.name}}</view>
									<view class="address">{{item.distance+' | '+item.address}}</view>
								</view>
								<image v-if="resultindex==index" src="../../static/newimg/Vector.png" class="dui" mode="">
								</image>
							</view>
						
					</scroll-view>
				</view>
			</view>
		</view>
	</view>
</template>

<script>
	import QQMapWX from "../../http/qqmap-wx-jssdk.js"
	export default {

		data() {
			return {
				mh: 0.65,
				sh: 0.3,
				bh:0.35,
				senceh:'',//屏幕高度
				sencew:'',//屏幕宽度
				mleft:0.5,//定位左
				mtop:0.5,//定位上
				menu: '',
				system: '',
				systemBar: '',
				navigationBar: '',
				mt: 0,

				model: {}, //当前选中点
				distance: '', //距离多远
				areaShow: false, //底部信息显示 
				isin: false,
				tittle: '定位',
				id: 0, // 使用 marker点击事件 需要填写id
				title: 'map',
				status: '', //状态
				fromlat:'',
				fromlng:'',
				latitude: '',
				longitude: '',
				toLatitude: '',
				toLongitude: '',
				covers: [],
				mar: [],
				isScale: 16,
				polygons: [], //	多边形
				polylines: [], //连线
				inputname: '', //搜索框输入
				resultpoint: [], //搜索到的地址
				resultindex: 0,
				location: '', //地址
				qqmapsdk: null, //腾讯sdk类
				isfocus:false,
				issearch:false,
				lat:'',//上次的
				lng:'',//上次的
				isfirst:true//第一次选
			}
		},
		onLoad(options) {
			//获取系统信息
			uni.getSystemInfo({ success: res => { this.system = res } })
			this.senceh=this.system.screenHeight
			this.sencew=this.system.screenWidth
			//获取胶囊信息
			this.menu = uni.getMenuButtonBoundingClientRect()
			this.systemBar = this.system.statusBarHeight //状态栏高度
			this.navigationBar = (this.menu.top)+ this.menu.height/2 //胶囊高度
			this.mt = this.navigationBar-10
			this.mleft=(this.sencew-31)/2
			this.mtop=(this.senceh*this.mh)/2-50
			 
			//使用腾讯SDK
			this.qqmapsdk = new QQMapWX({
				key: '*****'
			});
			if (options.status) {
				this.status = options.status
			}
			this.getStoreInfo() //获取服务区域==>没有接口可以自己取几个点
			if(options.lat){//已选地点
			//获取当前位置
				uni.authorize({
					scope: 'scope.userLocation',
					success:()=>{
						uni.getLocation({
							type: 'gcj02',
							success: (res) => {
								this.fromlat = res.latitude
								this.fromlng = res.longitude
								this.lat=Number(options.lat)
								this.lng=Number(options.lng)
								this.latitude=Number(options.lat)
								this.longitude=Number(options.lng)
								this.resultindex=options.index
								this.txrecode(this.lat,this.lng)
								this.model=this.resultpoint[this.resultindex]
							}
						})
					}
				})
				this.isfirst=false
			}
			else{
				//获取当前位置
				uni.authorize({
					scope: 'scope.userLocation',
					success:()=>{
						uni.getLocation({
							type: 'gcj02',
							success: (res) => {
								this.fromlat = res.latitude
								this.fromlng = res.longitude
								this.latitude = this.fromlat
								this.longitude = this.fromlng
							}
						})
					}
				})
				this.isfirst=true
			}
			
		},
		methods: {
			//拖动地图
			regionchange(event) {
				console.log('视野改变',event)
				if(event.detail.type=='begin'){
					let lat=event.target.centerLocation.latitude
					let lng=event.target.centerLocation.longitude
					if(this.lat){
						if(this.lat!=lat&&this.lng!=lng){
							this.latitude = this.fromlat
							this.longitude = this.fromlng
						}
					}
					
				}
				if (event.detail.type == 'end') {
					let lat=event.target.centerLocation.latitude
					let lng=event.target.centerLocation.longitude
					if(this.lat){
						if(this.lat!=lat&&this.lng!=lng){
							this.lat=''
							this.lng=''
							this.isfirst=true
							this.resultindex=0
						}
					}
					
					//非搜索,非第二次,非model
					if(!this.issearch&&this.isfirst||(this.model.latitude!=lat&&this.model.longitude!=lng)){
						this.resultindex=0
						console.log('当前视野改变')
						this.txrecode(lat,lng)
					}
				}
			},
			//聚焦搜索框
			focus() {
				this.low()
				this.isfocus=true
				if(this.inputname==''||this.inputname==null||!this.inputname||this.inputname.length==0){
					this.resultpoint = []
				}
			},
			//失焦
			blur(){
				this.top()
				this.isfocus=false
			},
			//滚动监听
			mov(e) {
				if (e.detail.scrollTop > 100) {
					this.low()
				} else {
					this.top()
				}
			},
			//触底
			low() {
				this.mh = 0.35
				this.bh=0.65
				this.sh = 0.6
				this.mtop=(this.senceh*this.mh)/2-50
			},
			//触顶 
			top() {
				this.mh = 0.65
				this.bh=0.35
				this.sh = 0.3
				this.mtop=(this.senceh*this.mh)/2-50
			},
			//获取区域--画多边形
			getStoreInfo() {
				this.$http({
					url: '/api/repairOrder/getCanUseAddressArea'
				}).then(res => {
					console.log('服务区域')
					let areas = res.data.data
					for (let i = 0; i < areas.length; i++) { //区域数
						let points = areas[i].area.split(';')
						this.polylines.push({
							'points': [],
							'strokeColor': '#4B96F3',
							'fillColor': '#b0d4f360',
							'width': 3,
							'dottedLine': false, //是否虚线
							'arrowLine': false, //带箭头的线
						})
						for (let j = 0; j < points.length - 1; j++) {
							let xy = points[j].split(',')
							this.polylines[i].points.push({
								'latitude': Number(xy[0]),
								'longitude': Number(xy[1])
							})
						}
					}
				})
			},
			//回到定位
			backcenter() {
				uni.createMapContext("map1", this).moveToLocation({
					longitude: this.longitude,
					latitude: this.latitude,
					complete(res) {
						console.log('去中心', res)
					}
				})
			},
			//输入框搜索
			input(e) {
				this.inputname = e.detail.value
			},
			//关键词搜索
			search(info) {
				if (info) {
					this.resultindex = 0
					// 事件触发,调用接口
					var that = this;
					var loc = this.latitude + ',' + this.longitude
					this.issearch=true
					//关键词输入提示
					this. qqmapsdk.getSuggestion({
						//获取输入框值并设置keyword参数
						keyword: info, //用户输入的关键词,可设置固定值,如keyword:'KFC'
						//region:'北京', //设置城市名,限制关键词所示的地域范围,非必填参数
						location: loc, //设置周边搜索中心点
						policy:1,
						success: function(res) {//搜索成功后的回调
							console.log(res);
							let data = res.data
							that.resultpoint = []
							for (let i = 0; i < data.length; i++) {
								let hw = data[i]._distance
								if (hw && hw !== -1) {
									if (hw < 100) {
										hw = "100m内"
									} else if (hw < 1000) {
										hw = hw + 'm';
									}
									//转换成公里
									else {
										hw = (hw / 2 / 500).toFixed(2) + 'km'
									}
								} else {
									hw = "100m内"
								}
								that.resultpoint.push({
									distance: hw,
									address: data[i].address,
									district: data[i].title,
									latitude: data[i].location.lat,
									longitude: data[i].location.lng,
									name: data[i].title
								})
								that.model = that.resultpoint[0]
							}
						}
					})
				} else {
					this.txrecode(this.latitude, this.longitude)//获取用户定位周边信息
				}
			},
			//选择搜索结果的位置
			selectresult(index) {
				this.issearch=true
				this.resultindex = index
				let arr = []
				// arr=this.resultpoint[index].location.split(',')
				console.log('arr', arr)
				this.model = this.resultpoint[index]
				// this.covers[0] = this.model
				this.distance = this.model.distance
				uni.createMapContext("map1", this).moveToLocation({
					longitude: Number(this.resultpoint[index].longitude), //经
					latitude: Number(this.resultpoint[index].latitude), //纬度小
					complete(res) {
						console.log('列表里第',index,'个点', res)
					}
				})
				
				// 判断是否在区域内
				this.shexian(this.resultpoint[index].latitude, this.resultpoint[index].longitude)
				if (this.isin) {} else {
					uni.showToast({
						icon: 'none',
						title: '不在服务范围内'
					})
				}
			},
			
			// 点击地图上的任意位置
			selectpoint(e) {
				if (this.status == 0) {
					uni.createMapContext("map1", this).moveToLocation({
						longitude: e.detail.longitude,
						latitude: e.detail.latitude,
						complete(res) {
							console.log('去中心', res)
						}
					})
				}
			},
			//射线法计算点是否落在多边形内,lat,log分别做射线,--精确算法
			shexian(lat, log) {
				for (let w = 0; w < this.polylines.length; w++) {
					let cl = 0
					let cr = 0
					let points = this.polylines[w].points
					for (let i = 0; i < points.length - 1; i++) {
						let next = i + 1
						//两个连续的点连成的线与水平线和垂直线是否有交
						let a = (log - points[i].longitude) / (points[i + 1].longitude - points[i].longitude) * (points[i +
							1].latitude - points[i].latitude) + points[i].latitude
						// console.log('points',i,points[i].longitude,points[i+1].longitude,log)
						if (log <= points[i].longitude && log > points[next].longitude || log >= points[i].longitude &&
							log < points[next].longitude) {
							if (a < points[i].latitude && a > points[next].latitude || a > points[i].latitude && a <
								points[next].latitude) {
								if (a > lat) {
									cl++
								}
								if (a < lat) {
									cr++
								}
								console.log('有交点', i, i + 1, cl, cr)
							}
						}
					}
					if (cl % 2 == 1 && cr % 2 == 1) {
						console.log('在区域内', cl, cr, this.toLongitude, this.toLatitude)
						this.isin = true
						w = this.polylines.length
					} else {
						if (w == this.polylines.length - 1) {
							this.isin = false
						}
					}
				}

			},
			getDistance(toLatitude, toLongitude, latitude, longitude, i) {
				var that = this;
				var toloc = toLatitude + ',' + toLongitude
				var fromloc = latitude + ',' + longitude
				//调用距离计算接口
				this.qqmapsdk.calculateDistance({
					//mode: 'driving',//可选值:'driving'(驾车)、'walking'(步行),不填默认:'walking',可不填
					//from参数不填默认当前地址
					//获取表单提交的经纬度并设置from和to参数(示例为string格式)
					from: fromloc || '', //若起点有数据则采用起点坐标,若为空默认当前地址
					to: toloc, //终点坐标
					success: function(res) { //成功后的回调
						console.log('算距离成功',res);
						let data = res.result.elements[0]
						// console.log('距离项', data);
						let hw = data.distance
						if (hw && hw !== -1) {
							if (hw < 100) {
								hw = "100m内"
							} else if (hw < 1000) {
								hw = hw + 'm';
							}
							//转换成公里
							else {
								hw = (hw / 2 / 500).toFixed(2) + 'km'
							}
						} else {
							hw = "100m内"
						}
						console.log(hw);
						that.resultpoint[i].distance = hw
						if(that.resultindex!=0){
							that.model=that.resultpoint[that.resultindex]
						}
						else{
							that.model = that.resultpoint[0]
						}
					},
					fail: function(error) {
						console.error(error);
					},
					complete: function(res) {
					}
				})
			},
			//逆转
			txrecode(latitude, longitude) {
				this.resultpoint = []
				let that = this
				var loc = latitude + ',' + longitude
				this.qqmapsdk.reverseGeocoder({
					location: loc,
					get_poi: 1,
					success: function(res) { //成功后的回调
						console.log('腾讯', res);
						var pois = res.result.pois

						for (let i = 0; i < pois.length; i++) {
							setTimeout(() => {
								that.resultpoint.push({
									distance: '',
									address: pois[i].address,
									district: pois[i].title,
									latitude: latitude,
									longitude: longitude,
									name: pois[i].title
								})
								that.getDistance(pois[i].location.lat, pois[i].location.lng, that.fromlat, that.fromlng, i)
								if(i=pois.length){
									that.model = that.resultpoint[that.resultindex]
								}
							}, 300 * i)
							
						}

					},
					fail: function(error) {
						console.error(error);
					},
					complete: function(res) {
					}
				})
			},
			markertap(e) {
				//this.areaShow = true //某个点显示
				var markerId = e.detail.markerId;
				this.model = this.covers.filter(t => t.id == markerId)[0]; //点击图片的对象
				var markerIndex = this.covers.findIndex(t => t.id == markerId);
				this.toLatitude = this.model.latitude
				this.toLongitude = this.model.longitude
			},
			//取消
			cancle() {
				uni.navigateBack({})
			},
			// 确定
			confirmbtn() {
				this.shexian(this.model.latitude, this.model.longitude)
				if (this.isin == false) return uni.showToast({
					icon: 'none',
					title: '请选择服务区内地址'
				})
				var pages = getCurrentPages();
				var prevPage = pages[pages.length - 2]; //上一个页面
				var object = {
					mapId: this.model.storeId,
					storeName: this.model.name,
					latitude: this.model.latitude,
					longitude: this.model.longitude,
					address: this.model.address,
					resultindex:this.resultindex,
				}
				prevPage.$vm.otherFun(object); //重点$vm
				uni.navigateBack();

			}
		}
	}
</script>

<style lang="scss">
	.body {
		width: 100%;
		height: 100vh;
		position: relative;
	}

	.btns {
		position: absolute;
		left: 30rpx;
		padding:0 30rpx;
		font-size: 30rpx;

		.cancle {
			width: 120rpx;
			height: 60rpx;
			line-height: 60rpx;
			border-radius: 10rpx;
			color: #FFFFFF;
			font-weight: 700;
			text-align: center;
			margin-right: 400rpx;
			background: #999999;
		}
	}

	.confirm {
		width: 120rpx;
		height: 60rpx;
		line-height: 60rpx;
		border-radius: 20rpx;
		background: #406333;
		color: #FFFFFF;
		text-align: center;
		margin-left: 30rpx;
	}

	.result {
		position: absolute;
		bottom: 0rpx;
		left: 0rpx;
		right: 0rpx;

		.end {
			display: flex;
			justify-content: flex-end;
		}

		.ricon {
			width: 100rpx;
			height: 100rpx;
			margin: 10rpx;
		}

		.info {
			border-radius: 20rpx 20rpx 0 0;
			background: #FFFFFF;

			.scroll {
				height: 400rpx;

				.item {
					display: flex;
					justify-content: space-between;
					align-items: center;
					border-bottom: 2rpx solid #f5f5f5;
					padding: 30rpx;

					.name {
						font-size: 30rpx;
						font-family: PingFang SC;
						font-weight: 500;
						color: #333333;
						line-height: 48rpx;
					}

					.address {
						font-size: 26rpx;
						font-family: PingFang SC;
						font-weight: 500;
						color: #666666;
						line-height: 48rpx;
						max-width: 600rpx;
					}

					.dui {
						width: 50rpx;
						height: 50rpx;
					}
				}
			}
		}
	}

	.search {
		padding: 30rpx;

		.sinfo {

			display: flex;
			justify-content: center;
			align-items: center;

			.input {
				display: flex;
				justify-content: center;
				align-items: center;
				background: #f5f5f5;
				border-radius: 20rpx;
				padding: 10rpx 30rpx;

				.icon {
					width: 30rpx;
					height: 30rpx;
					margin: 10rpx;
				}

				input {
					width: 400rpx;
					padding: 0 30rpx;
				}
			}
		}

		.text {
			font-size: 28rpx;
			font-family: PingFang SC;
			font-weight: 500;
			color: #9CA1B9;
		}
	}
</style>

这里面样式写的很不规范,大体功能可用,慎用,需自己申请腾讯地图key

注意

用户使用前必须授权定位

小程序使用以上接口需申请接口

 4>授权定位权限

首先要检查授权状态,已授权的就可继续定位等功能,未授权则APP提示或小程序跳转设置

getauthorize(){
// #ifdef MP-WEIXIN
	console.log('请求授权状态')
	const that=this
	uni.authorize({
		scope:'scope.userLocation',
		success() {
			console.log('成功授权')
			that.getlocation();
		},
		fail() {
			console.log('未授权')
			that.getopenconfirm()
		}
	})		
// #endif
	
// #ifdef APP-PLUS
	plus.geolocation.getCurrentPosition(function(p){
		that.resrLocation(p.coords.latitude,p.coords.longitude)
	}, function(e){
		if(e.message=='get location fail.'){
			uni.showToast({
				icon:'none',
				title:'请打开GPS定位服务'
			})
		}
		else{
			uni.showToast({
				icon:'none',
				title:e.message
			})
		}
	})
// #endif
},
//获取当前地理位置
getlocation(){
	uni.getLocation({
		type:'gcj02',
		altitude:true,
		success: (res) => {
			console.log('请求当前位置',res)
			//this.resrLocation(res.latitude,res.longitude)
		}
	})
},
//授权弹出
getopenconfirm(){
	uni.showModal({
		title:'请求授权当前位置',
		content:'需要获取您的地理位置提供服务,请确认授权',
		success: (res) => {
			if(res.confirm){
				uni.openSetting({})
			}
			else if(res.cancel){
				uni.showToast({
					title:'您拒绝了授权,无法获得定位信息,为您提供默认地址信息',
						icon:'none',
						duration:1000
				})
			}
		}
	})
},

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值