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
})
}
}
})
},