百度地图JavascriptApi Marker平滑移动及车头指向行径方向


Posted in Javascript onMarch 13, 2017

相信只要是使用百度地图做实时定位服务的朋友都会遇到这个问题,在对坐标位置进行覆盖物展示的时候,会出现由于获取坐标数据时间或者两个坐标点相距过远,导致在视觉上看Marker移动就像“僵尸跳”一样,一蹦一蹦的给客户看分分钟鄙视你到不能自已。另外如果用的是有指向性图标ICON的时候,更会引来吐槽~诶诶诶,你这小车车怎么在这个立交桥转弯的时候车头向着后面呢?怎么搞得嘛你!会不会弄啊你!

所以今天参照百度大大提供的路书开源文件实现下自己的需求,记录一下以便提供参考。

一、覆盖物在获取坐标数据的同时,在坐标点之间平滑的移动

首先,之所以会出现僵尸跳的效果,是因为项目是根据实时坐标数据进行定位,所以存在一个等待新数据的过程,而对于覆盖物的坐标改变就是一个setPosition(BMap.Point)方法而已也就造成了停顿。所以目前暂且解决方案就是:让他这个覆盖物在这个等待的期间找点事情做,不要一下就直接从起点蹦到终点了,慢慢的移动过去。小碎步,平滑的的移动过去~~

怎么移动呢?此时这个事情就可以转化为已知起始点坐标,进行移动覆盖物的这么过程了,说白了就是让他覆盖物在两个点连成的这条线上多执行几次setPosition(BMap.Point),一次步子别迈那么大,只要保证在下次新坐标来之前到达就行了。

那么问题又来了,这两条线上的点我怎么知道呢? 因为获取到的经纬度坐标是球面坐标,所以要先转换为平面坐标

{BMap.Pixel}= map.getMapType().getProjection().lngLatToPoint(BMap.Point);

然后小运算下(参照路书开源文件)

/*
 *缓动效果
 *初始坐标,目标坐标,当前的步长,总的步长
 *@param{BMap.Pixel} initPos 初始平面坐标
 *@parm{BMap.Pixel} targetPos 目标平面坐标
 *@param{number} 当前帧数
 *@param {number} count 总帧数
 */
 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);

经过计算得到的是一个平面坐标pixel(x,y)。然后再将平面坐标转换为球面坐标给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));

修改覆盖物定位坐标值。当然这个地方要进行多次执行也就需要个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,
    //当前帧数
    currentCount = 0,
    //初始坐标
    _prvePoint = me._projection.lngLatToPoint(prvePoint),//将球面坐标转换为平面坐标
    //获取结束点的(x,y)坐标
    _newPoint = me._projection.lngLatToPoint(newPoint),
    //两点之间要循环定位的次数
    count = me._runTime / me._intervalTimer;
    //两点之间匀速移动
    me._intervalFlag = setInterval(function () {
     //两点之间当前帧数大于总帧数的时候,则说明已经完成移动
     if (currentCount >= count) {
     clearInterval(me._intervalFlag);
     } else {
    //动画移动
    currentCount++;//计数
      var x = effect(_prvePoint.x, _newPoint.x, currentCount, count),
       y = effect(_prvePoint.y, _newPoint.y, currentCount, count);
      //根据平面坐标转化为球面坐标
    var pos = map.getMapType().getProjection().pointToLngLat(new BMap.Pixel(x, y));
    //设置marker角度(两点之间的距离车的角度保持一致)
     if (currentCount == 1) {
      //转换角度                     setRotation(prvePoint,newPoint, me._em);
     }
      //正在移动
    me._em._newPointMark.setPosition(pos);
   }
    }, me._intervalTimer);
    me._em._prvePoint = newPoint;
 }

值得注意的是,这里关键的就是这个count = me._runTime / me._intervalTimer; 决定了在这两个点之间要走多少个小碎步~~

这个count的由来也得根据自身项目需求计算。

1,通过控制覆盖物移动数据控制动画效果。这种方法就需要通过 速度与每次执行的时间计算得到每次执行前进的距离,然后在与两点之间的距离做商得到要执行的次数。(这种方法呢适合做历史轨迹回放这种,所有坐标信息都已经知道,一个点执行完就跳到下一个坐标,只是通过控制速度来控制动画的展示快慢)

2,通过控制平缓移动过程的总时间与每次执行间隔时间来控制动画效果。此方法就是文中的示例,直接二者做商即可得到要执行的次数。(这种方法适合做实时定位使用,因为下一次定位数据是间隔多少时间后接收,这个使我们可以控制的,所以这个平缓移动的动画过程的总时间也是可以由我们自己控制的) 

二、车头指向行径方向

这个功能其实就是改变覆盖物的旋转角度em._newPointMark.setRotation(number);

只是还是那个原因,因为得到的坐标点数据是球面坐标,所以还是要先进行转为平面坐标才好计算,然后通过三角函数tan#$%^&*( 计算后得到两个点之间的角度值。此部分没有太多个性化的逻辑操作,直接参照百度大大的就行了。

/**
 *在每个点的真实步骤中设置小车转动的角度
 *@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;
  }

参考计算方法就得了~~~

值此两个功能的最基础的及计算方法等就这么多,其他的业务逻辑需要的逻辑代码包裹着就是自己的需求实现代码了!

效果图

百度地图JavascriptApi Marker平滑移动及车头指向行径方向

百度地图JavascriptApi Marker平滑移动及车头指向行径方向

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

Javascript 相关文章推荐
jquery 实现checkbox全选,反选,全不选等功能代码(奇数)
Oct 24 Javascript
js实现ifram取父窗口URL地址的方法
Feb 09 Javascript
JS实现超简单的鼠标拖动效果
Nov 02 Javascript
JavaScript基本类型值-Undefined、Null、Boolean
Feb 23 Javascript
详解AngularJs ui-router 路由的简单介绍
Apr 26 Javascript
vue中遇到的坑之变化检测问题(数组相关)
Oct 13 Javascript
JavaScript内存泄漏的处理方式
Nov 20 Javascript
vue.js中npm安装教程图解
Apr 10 Javascript
快速解决bootstrap下拉菜单无法隐藏的问题
Aug 10 Javascript
Bootstrap实现省市区三级联动(亲测可用)
Jul 26 Javascript
Vue自定义组件的四种方式示例详解
Feb 28 Javascript
vscode 配置vue+vetur+eslint+prettier自动格式化功能
Mar 23 Javascript
分享一个精简的vue.js 图片lazyload插件实例
Mar 13 #Javascript
常用的几个JQuery代码片段
Mar 13 #Javascript
Vue2.0利用 v-model 实现组件props双向绑定的优美解决方案
Mar 13 #Javascript
jquery实现表单获取短信验证码代码
Mar 13 #Javascript
基于vue2.0+vuex的日期选择组件功能实现
Mar 13 #Javascript
VUE实现日历组件功能
Mar 13 #Javascript
JS正则表达式判断有效数实例代码
Mar 13 #Javascript
You might like
PHP 数据结构 算法 三元组 Triplet
2011/07/02 PHP
PHP中计算字符串相似度的函数代码
2012/12/29 PHP
关于Sphinx创建全文检索的索引介绍
2013/06/25 PHP
PHP_SELF,SCRIPT_NAME,REQUEST_URI区别
2014/12/24 PHP
jQuery实现 注册时选择阅读条款 左右移动
2013/04/11 Javascript
jquery的父子兄弟节点查找示例代码
2014/03/03 Javascript
js实现背景图片感应鼠标变化的方法
2015/02/28 Javascript
JavaScript获取一个范围内日期的方法
2015/04/24 Javascript
js实现模拟银行卡账号输入显示效果
2015/11/18 Javascript
JS+CSS实现的漂亮渐变背景特效代码(6个渐变效果)
2016/03/25 Javascript
React.js入门学习第一篇
2016/03/30 Javascript
jqueryMobile 动态添加元素,展示刷新视图的实现方法
2016/05/28 Javascript
JS获取浮动(float)元素的style.left值为空的快速解决办法
2017/02/19 Javascript
浅谈微信小程序之官方UI框架we-ui使用教程
2018/08/20 Javascript
在vue中使用vue-echarts-v3的实例代码
2018/09/13 Javascript
python 排列组合之itertools
2013/03/20 Python
深入理解 Python 中的多线程 新手必看
2016/11/20 Python
Python 中pandas.read_excel详细介绍
2017/06/23 Python
Python Nose框架编写测试用例方法
2017/10/26 Python
15行Python代码带你轻松理解令牌桶算法
2018/03/21 Python
使用tensorflow实现线性回归
2018/09/08 Python
Pyqt5 实现跳转界面并关闭当前界面的方法
2019/06/19 Python
python+selenium 点击单选框-radio的实现方法
2019/09/03 Python
matplotlib 画动态图以及plt.ion()和plt.ioff()的使用详解
2021/01/05 Python
python利用xpath爬取网上数据并存储到django模型中
2021/02/26 Python
Html5移动端div固定到底部实现底部导航条的几种方式
2021/03/09 HTML / CSS
美体小铺瑞典官方网站:The Body Shop瑞典
2018/01/27 全球购物
L’AGENCE官网:加州女装品牌
2018/06/03 全球购物
TUMI香港官网:国际领先的行李箱、背囊品牌
2021/03/01 全球购物
料理师求职信
2014/01/30 职场文书
大学共青团员个人自我评价
2014/04/16 职场文书
初中作文评语大全
2014/04/23 职场文书
自查自纠工作情况报告
2014/10/29 职场文书
复兴之路观后感3000字
2015/06/02 职场文书
大学优秀学生主要事迹材料
2015/11/04 职场文书
个人工作总结怎么写?
2019/04/09 职场文书