如何在vue中使用百度地图添加自定义覆盖物(水波纹)动画效果

具体的应用场景简而言之就是需要我们在地图上添加如图中所示的自定义覆盖物。实现的过程作者分为以下两点给大家介绍介绍。

  • 水波紋的实现
  • 自定义覆盖物的实现

水波紋的实现

这个需求的实现肯定是离不开我们自己写自定义覆盖物的,那么首先我们来讨论一下水波纹动画的实现。

首先我们可以看到图中的覆盖物是由一个红心和水波紋组成,其中红心是固定不动的,那么我们可以直接这么写:

.radar {
 width: 40px;
 height: 40px;
 border-radius: 50%;
 background-color: red;
}
<div class="radar"></div>

这样子我们首先就实现了红心部分的样式。那么水波紋又是怎么实现的呢?

我们可以从图中观察得出先后总共有三个水波紋从里到外逐渐的往外扩散。我们单独从一个水波紋来看的话,其实往外扩散的原理是通过动画让水波紋的宽高逐渐递增到一定程度即可,具体扩散多大呢读者可以根据自己的需求设定水波紋的最后宽高。

水波紋的基本结构和样式实现如下:

.radar {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background-color: red;
    position: relative;
    .ripple {
         width: 40px;
         height: 40px;
         border-radius: 50%;
         position: absolute;
         top: 50%;
         left: 50%;
         transform: translate(-50%,-50%);
         border: 1px solid red;
         animation: ripple 2s linear infinite;
    }
}
<div class="radar">
    <div class="ripple"></div>
    <div class="ripple"></div>
    <div class="ripple"></div>
</div>

之所以将水波紋的dom节点嵌套在radar节点里面主要是做一个“子绝父相”定位以达到水波紋居中对齐的效果,这个应该很容易理解。至于水波紋的初始宽高呢,为了方便动画延迟时间的计算,我就设置为跟红心宽高相等即可,如果读者有兴趣可以尝试一下宽高设置在0~40px任意值的看看效果(作者盲猜动画可能会有点瑕疵,可能也不会------>“手动狗头”))。

至于动画的实现呢,这个就很简单了,我们只需要同时将水波紋的宽高都逐渐变大即可,但是有个点要注意一下就是水波紋最后是会消失的,这里我们利用opacity:0配合动画达到逐渐消失的效果。

@keyframes ripple {
    to {
     width: 150px;
     height: 150px;
     opacity: 0;
    }
}

代码到了这里,我们水波紋已经是实现了,但是不是少了点什么?说好的三个水波紋呢?

这个问题也很好解决,我们只需要给水波紋设置对应的动画延迟即可。

.radar :nth-child(1) {
    animation-delay: 0.666s;
}
.radar :nth-child(2) {
    animation-delay: 1.322s;
}

这样子我们就把水波紋给实现出来啦。

自定义覆盖物的实现

本次作者采用的是百度地图实现的需求,那么如何通过百度地图来实现自定义覆盖物呢?

其实百度地图开发文档中也很直白的向我们展示自定义覆盖物的开箱方法。这里作者用es6的class稍微改写了一下写法,道理都一样的,官方案例可以参考百度地图demo

自定义覆盖物实现分以下三步:

  • 定义构造函数并继承Overlay
  • 初始化自定义覆盖物
  • 绘制覆盖物

定义构造函数并继承Overlay

按照官网的说法是:“首先您需要定义自定义覆盖物的构造函数,通过构造函数参数可以传递一些自由的变量。设置自定义覆盖物对象的prototype属性为Overlay的实例,以便继承覆盖物基类”。

正在上传…重新上传取消

运用es6 class我们可以很快的实现:

其中point传递的是坐标位置,用于后续计算覆盖物在地图上的位置。

class RadarOverlay extends BMap.Overlay {
 constructor(point) {
  super();
  this.point = point;
 }
}

初始化自定义覆盖物

官方的说法是:“实现initialize方法,当调用map.addOverlay方法时,API会调用此方法。当调用map.addOverlay方法添加自定义覆盖物时,API会调用该对象的initialize方法用来初始化覆盖物,在初始化过程中需要创建覆盖物所需要的DOM元素,并添加到地图相应的容器中。这里我们选择添加在容器markerPane上。”

其实意思大概就是说,因为百度地图在添加overLay时会调用自定义覆盖物构造函数中的initialize方法,这个initialize方法是用来初始化覆盖物的,他会在初始化过程中创建所需要的DOM,因此我们要在我们自己的构造函数(这里我们用的是类)中实现一个initialize。

百度地图官网的方法:

那么我们就按照官网的要求,在类中定义一个initialize方法。其中template存的是我们初始化中所需要的DOM元素,这里的dom节点会比上文中实现水波纹的环节多了一个className为rader-box的父节点,因为在官网中我们也可以看到官方实例在创建DOM元素时给DOM节点添加了position:absolute的样式,但由于我们的radar节点的position为relative,所以我们需要在最外层多嵌套一层dom节点以确保整个dom相对于地图定位。当然啦该父节点的position也就为绝对定位

initialize(map) {
 this._map = map;
 const template = `<div class="radar-box">
  <div class="radar">
   <div class="ripple"></div>
   <div class="ripple"></div>
   <div class="ripple"></div>
  </div>
 </div>`;
 // 创建文档碎片
 const divFragment = document.createRange().createContextualFragment(template);
 const div = divFragment.querySelectorAll('.radar-box')[0];
 // 将div添加到覆盖物容器中
 map.getPanes().markerPane.appendChild(div);
 this._div = div;
 return div;
}

这样子我们就成功的在类中定义了一个initialize方法,至于为什么要将div添加到覆盖物容器中官网的也有如下说明:

大概就是说百度地图里面已经给我们提供了若干的覆盖物展示方法,我们自定义的覆盖物其实是保存在我们选择的其中某个覆盖物容器之下,有兴趣的小伙伴可以去了解一下各种覆盖物容器。。。

绘制覆盖物

这里作者继续抛砖引玉阿,官方的说法是:“到目前为止,我们仅仅把覆盖物添加到了地图上,但是并没有将它放置在正确的位置上。您需要在draw方法中设置覆盖物的位置,每当地图状态发生变化(比如:位置移动、级别变化)时,API都会调用覆盖物的draw方法,用于重新计算覆盖物的位置。通过map.pointToOverlayPixel方法可以将地理坐标转换到覆盖物的所需要的像素坐标。”

简单来讲就是比如地图缩放比例之后,会重新调用覆盖物中的draw方法,用于重新鸡算覆盖物的位置。

那么问题来了,draw方法哪里来的?

所以官方的意思是我们在自定义覆盖物中的构造函数定义一个draw方法,方法中我们利用百度地图的map.pointToOverlayPixel方法(用来将地理坐标转换为像素坐标)可以将地理坐标转换到覆盖物的所需要的像素坐标。
那么我们只需要在类中加入draw方法即可:

其中this.point就是我们构造函数中的point坐标点,40表示的是我们整个水波纹的初始宽高,读者其实可以将40改为可以传参的形式比如this.size,这样会方便后续代码的维护,这里为了直观的让读者理解就不讲太复杂了。

draw() {
 // 根据地理坐标转换为像素坐标,并设置给容器
 const position = this._map.pointToOverlayPixel(this.point);
 this._div.style.left = `${position.x - 40 / 2}px`;
 this._div.style.top = `${position.y - 40 / 2}px`;
}

到此,我们整个自定义覆盖物的类就已经实现了,整体代码图下(这里把40改为this.size代码维护起来稍微方便点):

class RadarOverlay extends BMap.Overlay {
 constructor(point, size) {
  super();
  this.point = point;
  this.size = size;
 }
 
 initialize(map) {
  this._map = map;
  const template = `<div class="radar-box">
    <div class="radar">
     <div class="ripple"></div>
     <div class="ripple"></div>
     <div class="ripple"></div>
    </div>
   </div>`;
  const divFragment = document.createRange().createContextualFragment(template);
  const div = divFragment.querySelectorAll('.radar-box')[0];
  map.getPanes().markerPane.appendChild(div);
  this._div = div;
  return div;
 }
 
 draw() {
  // 根据地理坐标转换为像素坐标,并设置给容器
  const position = this._map.pointToOverlayPixel(this.point);
  this._div.style.left = `${position.x - this.size / 2}px`;
  this._div.style.top = `${position.y - this.size / 2}px`;
 }
}

自定义覆盖物的使用

那既然我们都已经实现了自定义的覆盖物,第一件事当然就是把它给使用上,具体如下:

initMap() {
 const map = new BMap.Map(this.$refs.map);
 map.centerAndZoom(new BMap.Point(116.404, 39.915), 15);
 // 实例化我们要绘制自定义覆盖物的点坐标
 const point = new BMap.Point(116.404, 39.915);   
  // 实例化自定义覆盖物,将坐标点和水波纹的尺寸传进构造函数中
 const radar = new RadarOverlay(point, 40);  
 // 添加自定义覆盖物
 map.addOverlay(radar);
}

 效果如图:

结语

至于构造自定义覆盖物的其他内容,大佬们如果要深入的话可以参考百度地图的文档,里面讲的肯定要比作者更加详细(狗头)。如果文章的内容有问题话的欢迎留言点出,希望能与各路大佬们交流交流,喜欢作者的文章的话也别忘了给我点个赞,这对我来说很重要。

源码地址:百度地图自定义覆盖物: vue中使用百度地图创建自定义覆盖物

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Vue使用百度地图添加自定义覆盖物,可以使用vue-baidu-map这个库来实现。在vue-baidu-map,可以使用百度地图API提供的Overlay类来创建自定义覆盖物。 以下是在vue-baidu-map添加自定义覆盖物的步骤: 1. 安装vue-baidu-map 在终端运行以下命令来安装vue-baidu-map: ``` npm install vue-baidu-map --save ``` 2. 注册vue-baidu-map组件 在Vue组件注册vue-baidu-map组件: ``` import BaiduMap from 'vue-baidu-map' export default { components: { BaiduMap } } ``` 3. 在模板添加地图 在模板添加vue-baidu-map标签,并设置地图的心点和缩放级别: ``` <template> <div> <BaiduMap :center="center" :zoom="zoom"></BaiduMap> </div> </template> <script> export default { data() { return { center: {lng: 116.404, lat: 39.915}, zoom: 15 } } } </script> ``` 4. 创建自定义覆盖物Vue组件的mounted()生命周期函数,创建自定义覆盖物: ``` mounted() { const map = this.$refs.baiduMap.getBMap() const BMap = window.BMap const point = new BMap.Point(116.404, 39.915) const myIcon = new BMap.Icon('path/to/myIcon.png', new BMap.Size(30, 30)) const marker = new BMap.Marker(point, {icon: myIcon}) map.addOverlay(marker) } ``` 在上面的代码,我们创建了一个自定义覆盖物,它是一个图片标记,位于地图的(116.404, 39.915)处。我们使用BMap.Icon类来创建一个自定义图标,并使用BMap.Marker类来创建一个标记,并将它添加到地图。 5. 在模板显示自定义覆盖物 在模板添加自定义覆盖物的容器,并使用CSS样式设置容器的位置和大小: ``` <template> <div> <BaiduMap :center="center" :zoom="zoom"></BaiduMap> <div class="marker-container"></div> </div> </template> <style> .marker-container { position: absolute; left: 50%; top: 50%; width: 30px; height: 30px; margin-left: -15px; margin-top: -15px; } </style> ``` 在上面的代码,我们添加了一个名为"marker-container"的DIV容器,用于显示自定义覆盖物。我们使用CSS样式将容器放置在地图的心位置,并设置容器的大小为30x30,该大小与自定义图标的大小相同。 6. 显示水波纹效果 要在自定义覆盖物上显示水波纹效果,可以使用CSS3动画和JavaScript。以下是实现水波纹效果的代码: ``` mounted() { const map = this.$refs.baiduMap.getBMap() const BMap = window.BMap const point = new BMap.Point(116.404, 39.915) const myIcon = new BMap.Icon('path/to/myIcon.png', new BMap.Size(30, 30)) const marker = new BMap.Marker(point, {icon: myIcon}) map.addOverlay(marker) const ripple = document.createElement('div') ripple.classList.add('ripple') marker.getContent().appendChild(ripple) marker.addEventListener('click', e => { const x = e.offsetX const y = e.offsetY ripple.style.left = x + 'px' ripple.style.top = y + 'px' ripple.classList.add('ripple-active') setTimeout(() => { ripple.classList.remove('ripple-active') }, 1000) }) } ``` 在上面的代码,我们使用JavaScript创建了一个DIV元素,用于显示水波纹效果。我们将这个DIV元素添加自定义覆盖物的容器,并在自定义覆盖物添加了一个点击事件监听器。当用户点击自定义覆盖物时,我们获取点击位置的坐标,并将水波纹DIV元素定位到该位置,并添加CSS3动画类"ripple-active"来显示水波纹效果。我们在1秒后从水波纹DIV元素移除"ripple-active"类,以停止水波纹效果。 7. 添加CSS样式 最后,我们需要添加CSS样式来定义水波纹效果自定义覆盖物的样式: ``` .marker-container { position: absolute; left: 50%; top: 50%; width: 30px; height: 30px; margin-left: -15px; margin-top: -15px; } .ripple { position: absolute; border-radius: 50%; width: 50px; height: 50px; background-color: rgba(255, 255, 255, 0.5); transform: translate(-50%, -50%); opacity: 0; transition: opacity 1s linear; } .ripple-active { opacity: 1; } ``` 在上面的代码,我们定义了"marker-container"类来设置自定义覆盖物的样式,以及"ripple"和"ripple-active"类来设置水波纹效果的样式。我们使用"position: absolute"来定位元素,并使用"transform: translate(-50%, -50%)"将元素的心点设置为其父元素的心点。我们还使用"opacity"和"transition"属性来定义水波纹效果的透明度和过渡效果。 这样就可以在Vue使用百度地图添加自定义覆盖物水波纹)了。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值