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


Posted in Javascript onNovember 03, 2020

简介

一如既往,我来给大家分享一个项目中遇到的比较有意思的需求并介绍一下相应的实现过程。

话不多说,直接上图:

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

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

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

水波?的实现

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

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

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

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

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

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

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

<div class="radar">
 <div class="ripple"></div>
 <div class="ripple"></div>
 <div class="ripple"></div>
 </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;
 }
 }

之所以将水波?的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;
 }

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

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

自定义覆盖物的实现

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

其实百度地图开发文档中也很直白的向我们展示自定义覆盖物的开箱方法。这里作者用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。

百度地图官网的方法:

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

那么我们就按照官网的要求,在类中定义一个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中使用百度地图添加自定义覆盖物(水波纹)

结语

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

源码地址:https://gitee.com/zhao_jiahao/baidu-map-custom-cover

到此这篇关于如何在vue中使用百度地图添加自定义覆盖物(水波纹)的文章就介绍到这了,更多相关vue用百度地图添加自定义覆盖物内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
几个javascript操作word的参考代码
Oct 26 Javascript
javascript parseInt() 函数的进制转换注意细节
Jan 08 Javascript
深入理解Javascript里的依赖注入
Mar 19 Javascript
js的[defer]和[async]属性
Nov 24 Javascript
使用jQuery仿苹果官网焦点图特效
Dec 23 Javascript
JavaScript设计模式之适配器模式介绍
Dec 28 Javascript
jQuery中用dom操作替代正则表达式
Dec 29 Javascript
JavaScript实现下拉菜单的显示和隐藏
Jan 05 Javascript
JavaScript制作颜色反转小游戏
Sep 25 Javascript
使用jQuery.Pin垂直滚动时固定导航
May 24 jQuery
vue移动端微信授权登录插件封装的实例
Aug 28 Javascript
JavaScript对象访问器Getter及Setter原理解析
Dec 08 Javascript
JavaScript语法约定和程序调试原理解析
Nov 03 #Javascript
解决vux 中popup 组件Mask 遮罩在最上层的问题
Nov 03 #Javascript
React Native登录之指纹登录篇的示例代码
Nov 03 #Javascript
解决VantUI popup 弹窗不弹出或无蒙层的问题
Nov 03 #Javascript
wepy--用vantUI 实现上弹列表并选择相应的值操作
Nov 03 #Javascript
使用vant的地域控件追加全部选项
Nov 03 #Javascript
vue vant中picker组件的使用
Nov 03 #Javascript
You might like
PHP中new static() 和 new self() 的区别介绍
2015/01/09 PHP
CodeIgniter钩子用法实例详解
2016/01/20 PHP
php 策略模式原理与应用深入理解
2019/09/25 PHP
CCPry JS类库 代码
2009/10/30 Javascript
JavaScript实用技巧(一)
2010/08/16 Javascript
jQuery lazyload 的重复加载错误以及修复方法
2010/11/19 Javascript
javascript使用正则表达式检测IP地址
2014/12/03 Javascript
深入理解JavaScript的React框架的原理
2015/07/02 Javascript
JS非Alert实现网页右下角“未读信息”效果弹窗
2015/09/26 Javascript
jquery form表单获取内容以及绑定数据
2016/02/24 Javascript
JS如何判断浏览器类型和详细区分IE各版本浏览器
2017/03/04 Javascript
vue轮播图插件vue-concise-slider的使用
2018/03/13 Javascript
nuxt 页面路由配置,主页轮播组件开发操作
2020/11/05 Javascript
简单谈谈Python中的几种常见的数据类型
2017/02/10 Python
python snownlp情感分析简易demo(分享)
2017/06/04 Python
利用信号如何监控Django模型对象字段值的变化详解
2017/11/27 Python
python去除文件中重复的行实例
2018/06/29 Python
python 判断文件还是文件夹的简单实例
2019/06/10 Python
python实现集中式的病毒扫描功能详解
2019/07/09 Python
Django中密码的加密、验密、解密操作
2019/12/19 Python
python可视化text()函数使用详解
2020/02/11 Python
Javascript 高级手势使用介绍
2013/04/21 HTML / CSS
世界上最具创新性的增强型知名运动品牌:Proviz
2018/04/03 全球购物
求最大连续递增数字串(如"ads3sl456789DF3456ld345AA"中的"456789")
2015/09/11 面试题
学习十八大精神心得体会
2013/12/31 职场文书
保险公司早会主持词
2014/03/22 职场文书
司法建议书范文
2014/05/13 职场文书
开工典礼策划方案
2014/05/23 职场文书
2014年志愿者工作总结
2014/11/20 职场文书
运动与健康自我评价
2015/03/09 职场文书
2015年暑期社会实践方案
2015/07/14 职场文书
2016年国庆节新闻稿范文
2015/11/25 职场文书
2016年党员创先争优公开承诺书
2016/03/25 职场文书
医生行业员工的辞职信
2019/06/24 职场文书
python 爬取吉首大学网站成绩单
2021/06/02 Python
Golang原生rpc(rpc服务端源码解读)
2022/04/07 Golang