因为自己想在手机端开发一个应用要应用Vue框架,所以就想到了uni-app,其中一个模块就要加载地图并获取位置信息。这个uni官网给了api,调用也还方面,现就开发中的思路和几个关键方法进行说明,由于uni-app最开始就是以微信小程序为主的,所以他和微信开发者工具基本很类似,他们两个可以互相参考着学习。这里我还是以uni-app为主。
这里要特别注意的一点就是:绘制地图和获取位置信息是两件事。先获取位置信息,再将位置信息展现在地图上。
目录
1.绘制地图在手机端
直接将<map></map>标签放上去就可以通过浏览器F12看到一个小地图了,map标签的属性中中心经度longitude,中心纬度latitude,缩放级别scale是要给的,这些数据都放在data中,绑定在标签里,遵守vue以数据为中心驱动的方式。layer-style是腾讯地图中地图样式,可以不设定使用默认的,markers是用来标记你当前位置的。@tap用来获取你点击地图的操作的,后面会说。
详细信息属性看这里:https://uniapp.dcloud.io/component/map
这里有个小坑,就是你通过获取当前手机屏幕高度,宽度设置750rpx的方式想让地图全屏显示,在H5端调试确实没有问题,但是在HbuilderX中运行到真机基座上就会出现宽度不能填充的情况,无论你设置啥,宽度死活留白。后来发现只有在map标签中style设置width:100%,height:100vh。才能让地图在手机端满屏。
2.获取位置
获取位置在API中的位置模块里。注意的是这部分获取位置在H5端可能获取不到,官方说是因为请求的谷歌浏览器,谷歌被墙了。所以在调试这一块的时候一定要在手机上测试,使用HbuilderX上的真机运行调试基座。连接手机测试。
app平台高德SDK仅支持返回gcj02
下面看一下我都设置了那些参数:
这里说明一下,想获取address必须将geocode设置为true,在上面的data里。否则为空,要设置下timeout超时时间,这样不会无限请求位置。
基本思路就是先获取坐标,之后将坐标给map标签和markers各一份,就可以实现刚进入进行定位绘图功能。这里要注意下vue的生命周期函数执行的顺序时机问题。
3.点击地图确定位置
主要通过uni.chooseLocation接口
uni.chooseLocation({
success: function (res) {
console.log('位置名称:' + res.name);
console.log('详细地址:' + res.address);
console.log('纬度:' + res.latitude);
console.log('经度:' + res.longitude);
}
});
在map标签上注册tap事件,在对应的方法中调用这个接口即可。
4.效果图展示:
5.源码展示:
<!-- 获取位置的界面 -->
<template>
<view class='objView'>
<u-row class="myInfoRow">
<u-col span='12' style="font-size:17px">
经度:{{longitude}}    纬度:{{latitude}}
</u-col>
</u-row>
<u-row class="myInfoRow">
<u-col span='12'>
<textarea v-show="geocode" disabled=true type="primary" :value='position' placeholder="未加载出位置信息"> </textarea>
</u-col>
</u-row>
<u-row>
<u-col span='6'>
<u-button type="success" shape="square" @click="changePosition">刷新当前位置</u-button>
</u-col>
<u-col span='6'>
<u-button type="success" shape="square" @click="returnPosition">返回定位位置</u-button>
</u-col>
</u-row><br/>
<u-row>
<!-- style内嵌标签的写法才能让app端地图全屏展示 -->
<u-col span='12'>
<map
id="myMap"
ref="myMap"
:longitude="longitude"
:latitude="latitude"
:scale="scale"
@tap='clickmap'
:markers='covers'
style="width: 100%; height: 100vh;"
>
</map>
</u-col>
</u-row>
</view>
</template>
<script>
//这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
//例如:import 《组件名称》 from '《组件路径》';
export default {
//import引入的组件需要注入到对象中才能使用
components: {},
data() {
//这里存放数据
return {
id:0,
longitude:0,//记录实时点击位置
latitude:0,
originalLongitude:0,//记录用户当前真实位置随时返回
originalLatitude:0,
scale:'16',
//是否解析地址信息
geocode:true,
// 定位标记
covers:[
{
longitude:this.longitude,
latitude:this.latitude,
iconPath: '../../static/imgs/nowPosition.png',
width:30,
height:30,
label:{
content:'当前位置',
textAlign:'center',
color:'#FB3109'
}
}
],
//获取的地址信息
position:'',
//记录用户当前真实位置随时返回
originalPosition:''
};
},
//监听属性 类似于data概念
computed: {},
//监控data中的数据变化
watch: {
},
//方法集合
methods: {
//点击地图时触发
clickmap(info)
{
//console.log('点击地图时候触发',info),
uni.chooseLocation({
success: (res)=>{
this.position='位置名称:'+res.name+' 详细地址:'+res.address;
this.longitude=res.longitude;
this.latitude=res.latitude;
//为标记点经纬度重新赋值【在data中赋坐标的方式无效】
this.covers[0].longitude=res.longitude;
this.covers[0].latitude=res.latitude;
// console.log('位置名称:' + res.name);
// console.log('详细地址:' + res.address);
// console.log('纬度:' + res.latitude);
// console.log('经度:' + res.longitude);
},
fail:(err)=>{
uni.showToast({
title:'获取位置失败'
});
}
});
},
//返回原始定位位置
returnPosition(){
this.position=this.originalPosition;
this.longitude=this.originalLongitude;
this.latitude=this.originalLatitude;
//为标记点经纬度重新赋值【在data中赋坐标的方式无效】
this.covers[0].longitude=this.originalLongitude;
this.covers[0].latitude=this.originalLatitude;
},
//点击更改坐标
changePosition()
{
this.longitude=this.longitude;
this.latitude= this.latitude;
console.log('坐标刷新成功');
uni.showToast({
title:'坐标刷新成功'
});
},
//获取定位信息
getLocation()
{
uni.showLoading({
title:'正在获取定位'
});
uni.getLocation(
{
type:"gcj02",
timeout:'1000',
geocode:this.geocode,
success:(res) =>{
uni.hideLoading();
this.longitude=res.longitude;
this.latitude=res.latitude;
//把原始定位另存一份,便于返回
this.originalLongitude=res.longitude;
this.originalLatitude=res.latitude;
//为标记点经纬度重新赋值【在data中赋坐标的方式无效】
this.covers[0].longitude=res.longitude;
this.covers[0].latitude=res.latitude;
//将地址信息进行存储
let {address}=res
let {country,province,city,district,street,streetNum,poiName}=address;
// console.log('获取定位数据成功',res)
//拼接地址
let myPosition=country+'-'+province+'-'+city+'-'+district+'-'+street+'-'+streetNum+'-'+poiName;
this.position=myPosition;
//把原始定位另存一份,便于返回
this.originalPosition=myPosition;
//console.log(this.country,city)
},
fail:(err)=>{
uni.hideLoading();
uni.showModal({
title:'提示',
content:'位置信息获取失败(请确定定位功能是否打开)',
showCancel:false
});
}
},
);
}
},
//生命周期 - 创建完成(可以访问当前this实例)
created() {
//获取位置信息
this.getLocation();
},
//生命周期 - 挂载完成(可以访问DOM元素)
mounted() {
//获取当前地图的信息
// let myMapInfo=this.$refs.myMap
// console.log(myMapInfo)
},
beforeCreate() {}, //生命周期 - 创建之前
beforeMount() {}, //生命周期 - 挂载之前
beforeUpdate() {}, //生命周期 - 更新之前
updated() {}, //生命周期 - 更新之后
beforeDestroy() {}, //生命周期 - 销毁之前
destroyed() {}, //生命周期 - 销毁完成
activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
}
</script>
<style lang='css' scoped>
#myMap{
width: 750rpx ;
}
/* 信息栏高度 */
.myInfoRow{
height: 50px;
}
/* 让地址栏通栏展示 */
textarea{
width: 100%;
}
</style>
6.打包注意
最后要注意的是,若打包发布要申请对应地图的key ,要是手机APP要申请高德地图的key,微信要申请腾讯地图的key。
不同端,使用地图选择时基于的底层地图引擎不一样,如微信小程序和H5是腾讯地图,App和阿里小程序是高德地图,百度小程序是百度地图,详见地图map组件的使用注意事项。app中也可以使用百度定位,在manifest中配置,打包后生效。但app-nvue里只能用百度定位,不能用百度地图。另外选择地图、查看地图位置的API也仅支持高德地图。所以App端如无特殊必要,建议使用高德地图。
详细参考在这里:https://uniapp.dcloud.io/component/map