背景
最近产品要在地图上显示出来各个点位的经纬度和名称信息,点击后将 marker
移动至地图中心,同时缩放地图。
知识点
属性 | 说明 |
---|---|
id | 地图组件的id,必填,在这里主要是用来获取地图上下文 mapContext 对象 |
scale | 缩放级别,在这里主要是用来点击callout后缩放级别 |
show-location | 显示带有方向的当前定位点, 和将地图中心移动到当前定位点 moveToLocation 方法结合使用 |
longitude | 中心经度,点击 callout 变更为选中 marker 的经度 |
latitude | 中心纬度,点击 callout 变更为选中 marker 的纬度 |
markers | 标记点 |
markertap | marker 的点击事件,和下方 calloutTap 事件一致 |
calloutTap | callout 的点击事件,点击之后 marker 移动至地图中心,并缩放地图 |
createMapContext
使用 createMapContext
获取 map
上下文,第一个参数就是该地图组件的 id
,第二个参数传入组件实例this
,以操作组件内 <map>
组件,详情可查看
那这里为什么需要 this
呢?毕竟微信小程序中的 createMapContext
不需要
这是因为在 uni-app
中,组件实例的生命周期和小程序页面的生命周期是不同的。在小程序中,一个页面是一个独立的 JavaScript
文件,而在 uni-app
中,一个页面可能包含多个组件,这些组件有自己的数据和生命周期。因此,如果要在组件中使用 createMapContext
方法来创建地图上下文,就需要将组件实例作为第二个参数传递给该方法,以便在组件内部访问到地图上下文对象。
因此,将组件实例作为第二个参数传递给 uni.createMapContext
方法,可以确保在组件内部正确地创建和管理地图上下文对象,并且可以避免不同组件之间的地图上下文对象混淆的问题。同时,也方便了组件内部对地图上下文对象的调用和管理。
moveToLocation
moveToLocation会获取定位权限,并且需要在 show-location
配合使用,也就是设置为true
移动至地图中心
两种方式
- 动态设置
map
组件上的longitude
和latitude
,缺点是没有移动的动画,很生硬 - 使用
moveToLocation
方法继续进行移动,动画很流畅
所以这里采用了第二种方案
设置地图scale
在 iOS
上设置 scale
,它会根据当前的经纬度进行缩放,也就是 map组件
上的 longitude
和latitude
,由于动态设置经纬度会导致失去移动的动画,所以我们这里先调用 moveToLocation
方法将 marker
移动至地图中心,300ms (这里的300ms是我多次尝试出来的,并不是官方的,这里的时间按需设置)
之后移动动画完成再去设置经纬度,这样既有移动的动画,又可以进行正常缩放了
安卓一切正常
实现
<template>
<map id="myMap" :scale="scale" :show-location="true" :longitude="longitude" :latitude="latitude" :markers="markers" @markertap="calloutTap" @callouttap="calloutTap" />
</template>
<script>
export default {
data() {
return {
longitude: 116.397428, //中心点经度
latitude: 39.90923, //中心点纬度
markers: [] ,//所有点位信息
mapContext: null, //map上下文
scale: 10, //默认缩放级别
};
},
mounted() {
//获取map上下文
const mapContext = uni.createMapContext('myMap', this);
this.mapContext = mapContext;
//模拟请求
setTimeout(() => {
//对markers进行赋值
this.markers = [
{
id: 1,
longitude: 116.397428,
latitude: 39.90923,
callout: {
content: '标记1',
color: '#ffffff',
fontSize: 14,
borderRadius: 4,
bgColor: '#3cc51f',
padding: 8,
display: 'ALWAYS',
},
},
{
id: 2,
longitude: 116.407428,
latitude: 39.90923,
callout: {
content: '标记2',
color: '#ffffff',
fontSize: 14,
borderRadius: 4,
bgColor: '#3cc51f',
padding: 8,
display: 'ALWAYS',
},
},
{
id: 3,
longitude: 116.397428,
latitude: 39.91923,
callout: {
content: '标记3',
color: '#ffffff',
fontSize: 14,
borderRadius: 4,
bgColor: '#3cc51f',
padding: 8,
display: 'ALWAYS',
},
},
];
//将中心点经纬度设置成第一个点位的经纬度
this.longitude = this.markers[0].longitude;
this.latitude = this.markers[0].latitude;
//获取所有点的经纬度
const points = this.markers.map((marker) => ({ latitude: marker.latitude, longitude: marker.longitude }));
// 缩放视野展示所有经纬度 [上,右,下,左]
this.mapContext.includePoints({
points,
padding: [150, 150, 150, 150], // 设置地图边缘与 marker 的间距
});
}, 2000);
},
methods: {
//点击气泡,找到被点击的marker
calloutTap(e) {
const { markerId } = e.detail;
const marker = this.markers.find((m) => m.id === markerId);
marker && this.moveMarkerToCenter(marker);
},
moveMarkerToCenter(marker) {
//将marker移动至中心点
this.mapContext.moveToLocation({
longitude: marker.longitude,
latitude: marker.latitude,
success: (res) => {
//这里加300ms的延时是为了防止和moveToLocation功能冲突,保留地图移动的动画
const timer = setTimeout(() => {
this.longitude = marker.longitude;
this.latitude = marker.latitude;
clearTimeout(timer);
//进行缩放,设置为16
this.scale = 16;
}, 300);
},
});
},
},
};
</script>
<style lang="scss" scoped>
#myMap {
width: 100vw;
height: 100vh;
}
</style>
在上述代码中,我们在 mounted
钩子函数中获取了地图的上下文对象 mapContext
,发起请求为markers赋值,调用includePoints
方法来缩放视野展示点位等
在 calloutTap
方法中,通过 e.markerId
获取到当前点击的标记点的 id
,然后在 markers
数组中查找该标记点,获取它的经纬度,将其作为参数传递给 moveToLocation
方法,以使地图移动到该标记点的位置并缩放地图
最终效果如下图所示
结语
到这里,我们已经完成了在 Uniapp
微信小程序中绘制标记点和气泡,并实现标记点和气泡的点击事件,以及点击后将标记点移动到地图中心的功能。
都已经看到了这里了,麻烦各位大佬点个赞咯,谢谢!
祝大家都变得更强!
原文链接:https://juejin.cn/post/7237514744479219767 作者:道宁