小程序实现地图撒点、调起第三方app导航

小程序实现地图撒点、调起第三方app导航

需求描述

项目需要展示地图,并在地图上显示所有的地点的点位。点击点位弹出当前点位的位置信息,点击导航按钮选择app打开当前位置进行导航

实现思路

  • 项目用的是uniapp + vue3,小程序中有标签,直接用就行,不用像web端那样还得引入各种地图。
  • 很多人可能和我一样,没有写过调起app的功能,所以不知道调起app通过什么触发,我查阅了一些资料,发现wx官方提供了openMapApp()方法,后续会讲到
  • 废话不多说,进正题

实现过程

首先自然得写个标签引入地图啦

<map class="maps" id="myMap" width="750rpx"
      height="600rpx" scale="10" 
     :latitude="latitude" 
     :longitude="longitude" 
	 :markers="markers"  
	 :show-location="true"
	 @markertap="markertap" />
	 //id:用于获取这个地图内容,后续用得着,理解成获取这个dom也行
	 //width、height:地图基础宽高,必填的
	 //latitude、longitude:经纬度,地图的中心点,也是必填
	 //markers:地图上的点
	 //show-location:当前位置
	 //@markertap:地图上的点的点击事件
	 //scale:地图缩放大小,数值越大越精确(嗯...应该算比例尺吧,我这么理解)

引入地图以后,可以把经纬度和markers写个假数据看看

	//我这用的vue3,直接写在setup里,vue2写在data里就好了
	<script setup>
	const longitude = ref(110.299121)
	const latitude = ref(25.274215)
	const markers = ref([{
		id:1, //id必须有一个
		latitude: 110.299121, //纬度
		longitude: 25.274215, //经度
		width:25, //markers的宽
		height:38 //markers的高
	}])
	</script>

到这一步,编译代码预览一下,地图就已经出来了
显示地图
需求是一次性在地图上展示所有点位,一个点肯定显然是不够的,那多个点怎么写入呢?很简单,观察一下,markers是一个数组类型,既然是数组那就可以无限push

//先写个测试看看
for(let i=0;i<6;i++){
			//for循环加markes点位
			markers.value.push({
				id:i,
				latitude:listData.value[i].latitude,
				longitude: listData.value[i].longitude,
				width:25,
				height:38
			})
}

这时候地图上就拥有多个点了
地图多点位
点位出来,功能完成一半了,用过小程序定位导航的都知道,正常会显示当前点位的地址名称、详细地址、以及导航按钮,像这样
小程序自带定位信息
  其实想做到图片里这种效果,只需要调用uniapp的uni.openLocation()方法即可,具体参数可以看看官网uni.openLocation(OBJECT),但这个方法虽然省事,但点击以后他会跳转一个新的集成的页面,官方也说了“本API是一个非原子的封装界面,开发者如有定制需求,可自己做页面实现类似功能。”显然这个方法不适合我们,自己手搓吧
  首先写一写样式布局,如果复制代码,记得把图片替换成你需要的
view部分

<!-- v-if主要用来切换当前视图是否展示 -->
<!-- adressName、adressphone、adressDetail下文会提到 -->
<!-- adressName——地址名称、adressphone——联系电话、adressDetail——详细地址 
	 下文会提到 -->
<view class="btmbox" v-if="adressName != ''">
			<view class="maxbox">
				<view class="btmtit">
					{{adressName}}
				</view>
				<view class="btmadre">
					{{adressDetail}}
				</view>
				<view class="btmadre">
					{{adressphone}}
				</view>
			</view>
			<view class="rightbox">
				<view class="toapp"  @click="toMapApp">
				<!-- img 记得替换 -->
					<img src="../../../../static/img/daohang.png" alt="" srcset="" style="width: 100%;height: 100%;">
				</view>
			</view>
			
		</view>

CSS部分

.btmbox{
		width: calc(100% - 60rpx);
		box-sizing: border-box;
		margin: 30rpx;
		padding: 30rpx;
		border-radius: 30rpx;
		// height: 200rpx;
		background: white;
		border-color: black;
		position: absolute;
		bottom: 100rpx;
		line-height: 52rpx;
		box-shadow: #b1b1b1 10rpx;
		display: flex;
		.maxbox{
			width: 80%;
			.btmtit{
				width: 100%;
				font-size: 36rpx;
				font-weight: bold;
			}
			.btmadre{
				width: 100%;
				font-size: 32rpx;
				color: #b1b1b1;
			}
		}
		.rightbox{
			width: 20%;
			.toapp{
				margin: 30rpx auto;
				width: 80rpx;
				height: 80rpx;
				border-radius: 50%;
			}
		}
		
	}

把假数据adressName——地址名称、adressphone——联系电话、adressDetail——详细地址 一一对应写进去,就得到了这个样子的页面
定位

大致页面效果就出来了,那怎么动态给所有的点绑定上数据呢?很简单,markers不是循环出来的嘛,循环的时候设置了id,id是唯一的,只要和后端数据对上就行了,我们把刚刚的循环语句改造一下,加上请求后端数据

	const listData = ref(null) //用于接收后端数据
	const markers = ref([]) //定义空的markers数组
	getAppraisalList().then(res=>{ //调接口取值
		listData.value = res.data //将后端的数据赋值给listData 
		//如果需要将后端传过来的第一个点作为中心点,可以写下面两行代码给默认经纬度赋值
		longitude.value = listData.value[0].longitude 
		latitude.value = listData.value[0].latitude
		for(let i=0;i<listData.value.length;i++){
			//for循环加markes点位
			markers.value.push({
				id:i,
				latitude:listData.value[i].latitude,
				longitude: listData.value[i].longitude,
				width:25,
				height:38
			})
		}
		
		//res.data的数据格式:
		[{
			address: "xx市xx路x号"
			divisionId: 2
			id: 5
			introduce: null
			latitude: 25.28727251510917
			longitude: 110.30042297938228
			name: "xx司法鉴定所"
			phone: "0773-2xxxx"}
		}]

这时候,数据和点的信息就绑定上了,只需要给markers绑定上点击事件(也就是上文提到的@markertap),就可以对应展示数据了

const adressName = ref('') //事务所名称
const adressDetail = ref('') //详细地址
const adressphone = ref('') //联系电话
const adressLatitude = ref(0) //传给app的纬度
const adressLongitude = ref(0) //传给app的经度
const markertap = (e) =>{
	adressName.value = listData.value[e.detail.markerId].name 
	adressDetail.value = listData.value[e.detail.markerId].address
	adressphone.value = listData.value[e.detail.markerId].phone
	adressLatitude.value = listData.value[e.detail.markerId].latitude
	adressLongitude.value = listData.value[e.detail.markerId].longitude
}

定位

最后,只差点击右侧下方的导航按钮选择app打开位置进行导航了,查了很多资料,发现可以使用微信的 openMapApp()方法,首先需要获取这个地图对象,这时候,上文设置的*id=“myMap”*作用就来了

//使用uni.getLocation()方法获取自身定位,可以将地图默认中心定在自己所在位置,这个不是必须的,可以不用
uni.getLocation({
	        type: 'gcj02', // 指定坐标类型为国测局坐标系(GCJ-02)
	        success(res) {
	           latitude.value = res.latitude; // 获取纬度赋值
	           longitude.value = res.longitude; // 获取经度赋值
	        },
	        fail(err) {
	          console.error('获取经纬度失败:', err);
	        }
});
//使用uni.createMapContext()方法获取地图对象
const MapContext = uni.createMapContext('myMap')
//接着调用方法
//调起app
const toMapApp = () =>{
    //openMapApp()方法主要用于拉起地图app选择导航
	MapContext.openMapApp({
		//因为不保证经纬度在传输过程中类型是否是number类型,所以使用Number转换
		latitude: Number(adressLatitude.value),
		longitude: Number(adressLongitude.value),
		//destination地址名称
		destination: adressName.value,
		success: function(e) {
			console.log(e)
			console.log('成功')
		},
		fail: function(e) {
			console.log(e)
			console.log('失败')
		}
	})
}

如果你用了uni.getLocation()这时候你以为成功了,实际上大概率你会得到这么一条报错

获取经纬度失败:
{errMsg: "getLocation:fail the api need to be declared in the requiredPrivateInfos field in app.json/ext.json"}

很好解决,项目找到manifest.json文件,在文件中找到"mp-weixin" : {}这个对象,复制以下代码

"requiredPrivateInfos" : [ "getLocation" ],
        "permission" : {
            "scope.userLocation" : {
                "desc" : "你的位置信息将用于小程序位置接口的效果展示"
            }
}

搞定,直接上真机测试over~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值