如何在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 相关文章推荐
innerText和innerHTML 一些问题分析
May 18 Javascript
基于js实现投票的实例代码
Aug 04 Javascript
深入理解JavaScript中的call、apply、bind方法的区别
May 30 Javascript
JS实现简单的右下角弹出提示窗口完整实例
Jun 21 Javascript
jQuery 实现ajax传入参数含有特殊字符的方法总结
Oct 17 Javascript
文件上传的几个示例分享【推荐】
Dec 16 Javascript
基于datepicker定义自己的angular时间组件的示例
Mar 14 Javascript
微信小程序BindTap快速连续点击目标页面跳转多次问题处理
Apr 08 Javascript
Vue v-text指令简单使用方法示例
Sep 19 Javascript
vue-cli 为项目设置别名的方法
Oct 15 Javascript
vue中实现回车键登录功能
Feb 19 Javascript
使用JavaScript通过前端发送电子邮件
May 22 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生成静态HTML速度快类库
2007/03/18 PHP
PHP6 mysql连接方式说明
2009/02/09 PHP
PHP使用GIFEncoder类生成gif动态滚动字幕
2014/07/01 PHP
CL vs ForZe BO5 第三场 2.13
2021/03/10 DOTA
javascript中普通函数的使用介绍
2013/12/19 Javascript
js获取日期:昨天今天和明天、后天
2014/06/11 Javascript
javascript异步编程代码书写规范Promise学习笔记
2015/02/11 Javascript
js实现千分符和保留几位小数的简单实例
2016/08/01 Javascript
基本DOM节点操作
2017/01/17 Javascript
Web制作验证码功能实例代码
2017/06/19 Javascript
jQuery菜单实例(全选,反选,取消)
2017/08/28 jQuery
axios 处理 302 状态码的解决方法
2018/04/10 Javascript
vue 本地环境跨域请求proxyTable的方法
2018/09/19 Javascript
vue中接口域名配置为全局变量的实现方法
2018/09/20 Javascript
vue计算属性computed的使用方法示例
2019/03/13 Javascript
vue 父组件给子组件传值子组件给父组件传值的实例代码
2019/04/15 Javascript
JS实现商品橱窗特效
2020/01/09 Javascript
[01:00:14]DOTA2-DPC中国联赛 正赛 Ehome vs Elephant BO3 第二场 2月28日
2021/03/11 DOTA
python三元运算符实现方法
2013/12/17 Python
Python复制目录结构脚本代码分享
2015/03/06 Python
Python的面向对象编程方式学习笔记
2016/07/12 Python
对Python实现累加函数的方法详解
2019/01/23 Python
Python基于class()实现面向对象原理详解
2020/03/26 Python
Python使用Excel将数据写入多个sheet
2020/05/16 Python
python实现图像外边界跟踪操作
2020/07/13 Python
HTML5 Canvas的常用线条属性值总结
2016/03/17 HTML / CSS
倩碧英国官网:Clinique英国
2018/08/10 全球购物
美国婴儿和儿童服装购物网站:PatPat
2020/10/01 全球购物
自考生自我评价分享
2014/01/18 职场文书
学校个人对照检查材料
2014/08/26 职场文书
法人委托书的范本格式
2014/09/11 职场文书
英语教师求职信范文
2015/03/20 职场文书
五星级酒店宣传口号
2015/12/25 职场文书
学校标语口号大全
2015/12/26 职场文书
《所见》教学反思
2016/02/23 职场文书
i5-10400f处理相当于i7多少水平
2022/04/19 数码科技