如何在vue中使用百度地圖添加自定義覆蓋物(水波紋)
簡介
一如既往,我來給大家分享一個項目中遇到的比較有意思的需求并介紹一下相應(yīng)的實現(xiàn)過程。
話不多說,直接上圖:
具體的應(yīng)用場景簡而言之就是需要我們在地圖上添加如圖中所示的自定義覆蓋物。實現(xiàn)的過程作者分為以下兩點給大家介紹介紹。
- 水波紋的實現(xiàn)
- 自定義覆蓋物的實現(xiàn)
水波紋的實現(xiàn)
這個需求的實現(xiàn)肯定是離不開我們自己寫自定義覆蓋物的,那么首先我們來討論一下水波紋動畫的實現(xiàn)。
首先我們可以看到圖中的覆蓋物是由一個紅心和水波紋組成,其中紅心是固定不動的,那么我們可以直接這么寫:
<div class="radar"></div>
.radar { width: 40px; height: 40px; border-radius: 50%; background-color: red; }
這樣子我們首先就實現(xiàn)了紅心部分的樣式。那么水波紋又是怎么實現(xiàn)的呢?
我們可以從圖中觀察得出先后總共有三個水波紋從里到外逐漸的往外擴散。我們單獨從一個水波紋來看的話,其實往外擴散的原理是通過動畫讓水波紋的寬高逐漸遞增到一定程度即可,具體擴散多大呢讀者可以根據(jù)自己的需求設(shè)定水波紋的最后寬高。
水波紋的基本結(jié)構(gòu)和樣式實現(xiàn)如下:
<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節(jié)點嵌套在radar節(jié)點里面主要是做一個“子絕父相”定位以達到水波紋居中對齊的效果,這個應(yīng)該很容易理解。至于水波紋的初始寬高呢,為了方便動畫延遲時間的計算,我就設(shè)置為跟紅心寬高相等即可,如果讀者有興趣可以嘗試一下寬高設(shè)置在0~40px任意值的看看效果(作者盲猜動畫可能會有點瑕疵,可能也不會------>“手動狗頭”))。
至于動畫的實現(xiàn)呢,這個就很簡單了,我們只需要同時將水波紋的寬高都逐漸變大即可,但是有個點要注意一下就是水波紋最后是會消失的,這里我們利用opacity:0配合動畫達到逐漸消失的效果。
@keyframes ripple { to { width: 150px; height: 150px; opacity: 0; } }
代碼到了這里,我們水波紋已經(jīng)是實現(xiàn)了,但是不是少了點什么?說好的三個水波紋呢?
這個問題也很好解決,我們只需要給水波紋設(shè)置對應(yīng)的動畫延遲即可。
.radar :nth-child(1) { animation-delay: 0.666s; } .radar :nth-child(2) { animation-delay: 1.322s; }
這樣子我們就把水波紋給實現(xiàn)出來啦。
自定義覆蓋物的實現(xiàn)
本次作者采用的是百度地圖實現(xiàn)的需求,那么如何通過百度地圖來實現(xiàn)自定義覆蓋物呢?
其實百度地圖開發(fā)文檔中也很直白的向我們展示自定義覆蓋物的開箱方法。這里作者用es6的class稍微改寫了一下寫法,道理都一樣的,官方案例可以參考百度地圖demo
自定義覆蓋物實現(xiàn)分以下三步:
- 定義構(gòu)造函數(shù)并繼承Overlay
- 初始化自定義覆蓋物
- 繪制覆蓋物
定義構(gòu)造函數(shù)并繼承Overlay
按照官網(wǎng)的說法是:“首先您需要定義自定義覆蓋物的構(gòu)造函數(shù),通過構(gòu)造函數(shù)參數(shù)可以傳遞一些自由的變量。設(shè)置自定義覆蓋物對象的prototype屬性為Overlay的實例,以便繼承覆蓋物基類”。
運用es6 class我們可以很快的實現(xiàn):
其中point傳遞的是坐標(biāo)位置,用于后續(xù)計算覆蓋物在地圖上的位置。
class RadarOverlay extends BMap.Overlay { constructor(point) { super(); this.point = point; } }
初始化自定義覆蓋物
官方的說法是:“實現(xiàn)initialize方法,當(dāng)調(diào)用map.addOverlay方法時,API會調(diào)用此方法。當(dāng)調(diào)用map.addOverlay方法添加自定義覆蓋物時,API會調(diào)用該對象的initialize方法用來初始化覆蓋物,在初始化過程中需要創(chuàng)建覆蓋物所需要的DOM元素,并添加到地圖相應(yīng)的容器中。這里我們選擇添加在容器markerPane上?!?/p>
其實意思大概就是說,因為百度地圖在添加overLay時會調(diào)用自定義覆蓋物構(gòu)造函數(shù)中的initialize方法,這個initialize方法是用來初始化覆蓋物的,他會在初始化過程中創(chuàng)建所需要的DOM,因此我們要在我們自己的構(gòu)造函數(shù)(這里我們用的是類)中實現(xiàn)一個initialize。
百度地圖官網(wǎng)的方法:
那么我們就按照官網(wǎng)的要求,在類中定義一個initialize方法。其中template存的是我們初始化中所需要的DOM元素,這里的dom節(jié)點會比上文中實現(xiàn)水波紋的環(huán)節(jié)多了一個className為rader-box的父節(jié)點,因為在官網(wǎng)中我們也可以看到官方實例在創(chuàng)建DOM元素時給DOM節(jié)點添加了position:absolute的樣式,但由于我們的radar節(jié)點的position為relative,所以我們需要在最外層多嵌套一層dom節(jié)點以確保整個dom相對于地圖定位。當(dāng)然啦該父節(jié)點的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>`; // 創(chuàng)建文檔碎片 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添加到覆蓋物容器中官網(wǎng)的也有如下說明:
大概就是說百度地圖里面已經(jīng)給我們提供了若干的覆蓋物展示方法,我們自定義的覆蓋物其實是保存在我們選擇的其中某個覆蓋物容器之下,有興趣的小伙伴可以去了解一下各種覆蓋物容器。。。
繪制覆蓋物
這里作者繼續(xù)拋磚引玉阿,官方的說法是:“到目前為止,我們僅僅把覆蓋物添加到了地圖上,但是并沒有將它放置在正確的位置上。您需要在draw方法中設(shè)置覆蓋物的位置,每當(dāng)?shù)貓D狀態(tài)發(fā)生變化(比如:位置移動、級別變化)時,API都會調(diào)用覆蓋物的draw方法,用于重新計算覆蓋物的位置。通過map.pointToOverlayPixel方法可以將地理坐標(biāo)轉(zhuǎn)換到覆蓋物的所需要的像素坐標(biāo)?!?/p>
簡單來講就是比如地圖縮放比例之后,會重新調(diào)用覆蓋物中的draw方法,用于重新雞算覆蓋物的位置。
那么問題來了,draw方法哪里來的?
所以官方的意思是我們在自定義覆蓋物中的構(gòu)造函數(shù)定義一個draw方法,方法中我們利用百度地圖的map.pointToOverlayPixel方法(用來將地理坐標(biāo)轉(zhuǎn)換為像素坐標(biāo))可以將地理坐標(biāo)轉(zhuǎn)換到覆蓋物的所需要的像素坐標(biāo)。
那么我們只需要在類中加入draw方法即可:
其中this.point就是我們構(gòu)造函數(shù)中的point坐標(biāo)點,40表示的是我們整個水波紋的初始寬高,讀者其實可以將40改為可以傳參的形式比如this.size,這樣會方便后續(xù)代碼的維護,這里為了直觀的讓讀者理解就不講太復(fù)雜了。
draw() { // 根據(jù)地理坐標(biāo)轉(zhuǎn)換為像素坐標(biāo),并設(shè)置給容器 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`; }
到此,我們整個自定義覆蓋物的類就已經(jīng)實現(xiàn)了,整體代碼圖下(這里把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() { // 根據(jù)地理坐標(biāo)轉(zhuǎn)換為像素坐標(biāo),并設(shè)置給容器 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`; } }
自定義覆蓋物的使用
那既然我們都已經(jīng)實現(xiàn)了自定義的覆蓋物,第一件事當(dāng)然就是把它給使用上,具體如下:
initMap() { const map = new BMap.Map(this.$refs.map); map.centerAndZoom(new BMap.Point(116.404, 39.915), 15); // 實例化我們要繪制自定義覆蓋物的點坐標(biāo) const point = new BMap.Point(116.404, 39.915); // 實例化自定義覆蓋物,將坐標(biāo)點和水波紋的尺寸傳進構(gòu)造函數(shù)中 const radar = new RadarOverlay(point, 40); // 添加自定義覆蓋物 map.addOverlay(radar); }
效果如圖:
結(jié)語
至于構(gòu)造自定義覆蓋物的其他內(nèi)容,大佬們?nèi)绻钊氲脑捒梢詤⒖及俣鹊貓D的文檔,里面講的肯定要比作者更加詳細(狗頭)。如果文章的內(nèi)容有問題話的歡迎留言點出,希望能與各路大佬們交流交流,喜歡作者的文章的話也別忘了給我點個贊,這對我來說很重要。
源碼地址:https://gitee.com/zhao_jiahao/baidu-map-custom-cover
到此這篇關(guān)于如何在vue中使用百度地圖添加自定義覆蓋物(水波紋)的文章就介紹到這了,更多相關(guān)vue用百度地圖添加自定義覆蓋物內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue中Axios添加攔截器刷新token的實現(xiàn)方法
Axios是一款網(wǎng)絡(luò)前端請求框架,本文主要介紹了vue中Axios添加攔截器刷新token的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-02-02Element中el-input密碼輸入框瀏覽器自動填充賬號密碼問題的解決方法
自己寫了一個管理系統(tǒng),登錄成功之后,瀏覽器提示我保存賬號密碼,每次登錄時就會自動回填記住的賬號密碼,方便用戶快速登錄,下面這篇文章主要給大家介紹了關(guān)于Element中el-input密碼輸入框瀏覽器自動填充賬號密碼問題的解決方法,需要的朋友可以參考下2022-09-09