百度地圖JavascriptApi Marker平滑移動及車頭指向行徑方向
相信只要是使用百度地圖做實時定位服務的朋友都會遇到這個問題,在對坐標位置進行覆蓋物展示的時候,會出現(xiàn)由于獲取坐標數(shù)據(jù)時間或者兩個坐標點相距過遠,導致在視覺上看Marker移動就像“僵尸跳”一樣,一蹦一蹦的給客戶看分分鐘鄙視你到不能自已。另外如果用的是有指向性圖標ICON的時候,更會引來吐槽~誒誒誒,你這小車車怎么在這個立交橋轉(zhuǎn)彎的時候車頭向著后面呢?怎么搞得嘛你!會不會弄啊你!
所以今天參照百度大大提供的路書開源文件實現(xiàn)下自己的需求,記錄一下以便提供參考。
一、覆蓋物在獲取坐標數(shù)據(jù)的同時,在坐標點之間平滑的移動
首先,之所以會出現(xiàn)僵尸跳的效果,是因為項目是根據(jù)實時坐標數(shù)據(jù)進行定位,所以存在一個等待新數(shù)據(jù)的過程,而對于覆蓋物的坐標改變就是一個setPosition(BMap.Point)方法而已也就造成了停頓。所以目前暫且解決方案就是:讓他這個覆蓋物在這個等待的期間找點事情做,不要一下就直接從起點蹦到終點了,慢慢的移動過去。小碎步,平滑的的移動過去~~
怎么移動呢?此時這個事情就可以轉(zhuǎn)化為已知起始點坐標,進行移動覆蓋物的這么過程了,說白了就是讓他覆蓋物在兩個點連成的這條線上多執(zhí)行幾次setPosition(BMap.Point),一次步子別邁那么大,只要保證在下次新坐標來之前到達就行了。
那么問題又來了,這兩條線上的點我怎么知道呢? 因為獲取到的經(jīng)緯度坐標是球面坐標,所以要先轉(zhuǎn)換為平面坐標
{BMap.Pixel}= map.getMapType().getProjection().lngLatToPoint(BMap.Point);
然后小運算下(參照路書開源文件)
/* *緩動效果 *初始坐標,目標坐標,當前的步長,總的步長 *@param{BMap.Pixel} initPos 初始平面坐標 *@parm{BMap.Pixel} targetPos 目標平面坐標 *@param{number} 當前幀數(shù) *@param {number} count 總幀數(shù) */ this.linear = function (initPos, targetPos, currentCount, count) { var b = initPos, c = targetPos - initPos, t = currentCount, d = count; return c * t / d + b; } var x = effect(_prvePoint.x, _newPoint.x, currentCount, count), y = effect(_prvePoint.y, _newPoint.y, currentCount, count);
經(jīng)過計算得到的是一個平面坐標pixel(x,y)。然后再將平面坐標轉(zhuǎn)換為球面坐標給Marker進行定位即可。(這些方法在百度類庫參考文檔中都可以找得到的。魔法門: http://developer.baidu.com/map/reference/index.php?title=Class:%E6%80%BB%E7%B1%BB/%E5%9C%B0%E5%9B%BE%E7%B1%BB%E5%9E%8B%E7%B1%BB)
var pos = map.getMapType().getProjection().pointToLngLat(new BMap.Pixel(x, y));
修改覆蓋物定位坐標值。當然這個地方要進行多次執(zhí)行也就需要個setInterval咯 這里面的
me._em._newPointMark.setPosition(pos);
完整方法:
/** *小車移動 *@param {Point} prvePoint 開始坐標(PrvePoint) *@param {Point} newPoint 目標點坐標 *@param {Function} 動畫效果 *@return 無返回值 */ this.Move = function (prvePoint, newPoint, effect, setRotation) { var me = this, //當前幀數(shù) currentCount = 0, //初始坐標 _prvePoint = me._projection.lngLatToPoint(prvePoint),//將球面坐標轉(zhuǎn)換為平面坐標 //獲取結(jié)束點的(x,y)坐標 _newPoint = me._projection.lngLatToPoint(newPoint), //兩點之間要循環(huán)定位的次數(shù) count = me._runTime / me._intervalTimer; //兩點之間勻速移動 me._intervalFlag = setInterval(function () { //兩點之間當前幀數(shù)大于總幀數(shù)的時候,則說明已經(jīng)完成移動 if (currentCount >= count) { clearInterval(me._intervalFlag); } else { //動畫移動 currentCount++;//計數(shù) var x = effect(_prvePoint.x, _newPoint.x, currentCount, count), y = effect(_prvePoint.y, _newPoint.y, currentCount, count); //根據(jù)平面坐標轉(zhuǎn)化為球面坐標 var pos = map.getMapType().getProjection().pointToLngLat(new BMap.Pixel(x, y)); //設置marker角度(兩點之間的距離車的角度保持一致) if (currentCount == 1) { //轉(zhuǎn)換角度 setRotation(prvePoint,newPoint, me._em); } //正在移動 me._em._newPointMark.setPosition(pos); } }, me._intervalTimer); me._em._prvePoint = newPoint; }
值得注意的是,這里關鍵的就是這個count = me._runTime / me._intervalTimer; 決定了在這兩個點之間要走多少個小碎步~~
這個count的由來也得根據(jù)自身項目需求計算。
1,通過控制覆蓋物移動數(shù)據(jù)控制動畫效果。這種方法就需要通過 速度與每次執(zhí)行的時間計算得到每次執(zhí)行前進的距離,然后在與兩點之間的距離做商得到要執(zhí)行的次數(shù)。(這種方法呢適合做歷史軌跡回放這種,所有坐標信息都已經(jīng)知道,一個點執(zhí)行完就跳到下一個坐標,只是通過控制速度來控制動畫的展示快慢)
2,通過控制平緩移動過程的總時間與每次執(zhí)行間隔時間來控制動畫效果。此方法就是文中的示例,直接二者做商即可得到要執(zhí)行的次數(shù)。(這種方法適合做實時定位使用,因為下一次定位數(shù)據(jù)是間隔多少時間后接收,這個使我們可以控制的,所以這個平緩移動的動畫過程的總時間也是可以由我們自己控制的)
二、車頭指向行徑方向
這個功能其實就是改變覆蓋物的旋轉(zhuǎn)角度em._newPointMark.setRotation(number);
只是還是那個原因,因為得到的坐標點數(shù)據(jù)是球面坐標,所以還是要先進行轉(zhuǎn)為平面坐標才好計算,然后通過三角函數(shù)tan#$%^&*( 計算后得到兩個點之間的角度值。此部分沒有太多個性化的邏輯操作,直接參照百度大大的就行了。
/** *在每個點的真實步驟中設置小車轉(zhuǎn)動的角度 *@param{BMap.Point} curPos 起點 *@param{BMap.Point} targetPos 終點 */ this.setRotation = function (curPos, targetPos, em) { var me = this; var deg = 0; curPos = map.pointToPixel(curPos); targetPos = map.pointToPixel(targetPos); if (targetPos.x != curPos.x) { var tan = (targetPos.y - curPos.y) / (targetPos.x - curPos.x), atan = Math.atan(tan); deg = atan * 360 / (2 * Math.PI); if (targetPos.x < curPos.x) { deg = -deg + 90 + 90; } else { deg = -deg; } em._newPointMark.setRotation(-deg); } else { var disy = targetPos.y - curPos.y; var bias = 0; if (disy > 0) bias = -1 else bias = 1 em._newPointMark.setRotation(-bias * 90); } return; }
參考計算方法就得了~~~
值此兩個功能的最基礎的及計算方法等就這么多,其他的業(yè)務邏輯需要的邏輯代碼包裹著就是自己的需求實現(xiàn)代碼了!
效果圖
以上就是本文的全部內(nèi)容,希望本文的內(nèi)容對大家的學習或者工作能帶來一定的幫助,同時也希望多多支持腳本之家!
相關文章
微信小程序基于canvas漸變實現(xiàn)的彩虹效果示例
這篇文章主要介紹了微信小程序基于canvas漸變實現(xiàn)的彩虹效果,結(jié)合實例形式分析了微信小程序線性漸變及圓形漸變的相關實現(xiàn)技巧,需要的朋友可以參考下2019-05-05JavaScript 箭頭函數(shù)的特點、與普通函數(shù)的區(qū)別
這篇文章主要介紹了JavaScript 箭頭函數(shù)的特點、與普通函數(shù)的區(qū)別,很多情況下,箭頭函數(shù)和函數(shù)表達式創(chuàng)建的函數(shù)并無區(qū)別,只有寫法上的不同,本文第二塊內(nèi)容將介紹箭頭函數(shù)和普通函數(shù)功能上的區(qū)別,感興趣的朋友跟隨小編一起看看吧2021-11-11微信小程序使用wx.chooseLocation開發(fā)地圖怎么做
這篇文章主要介紹了微信小程序使用wx.chooseLocation開發(fā)地圖流程,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧2022-12-12