百度地图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 相关文章推荐
javascript开发中因空格引发的错误
Nov 08 Javascript
js的压缩及jquery压缩探讨(提高页面加载性能/保护劳动成果)
Jan 29 Javascript
IE与FireFox的JavaScript兼容问题解决办法
Dec 31 Javascript
jQuery浏览器CSS3特写兼容实例
Jan 19 Javascript
详解JavaScript语言的基本语法要求
Nov 20 Javascript
浅析javascript中的Event事件
Dec 09 Javascript
JS正则表达式之非捕获分组用法实例分析
Dec 28 Javascript
bootstrap IE8 兼容性处理
Mar 22 Javascript
JS实现上传图片实时预览功能
May 22 Javascript
微信小程序实现多宫格抽奖活动
Apr 15 Javascript
jQuery实现左右滑动的toggle方法
Mar 03 jQuery
bootstrapValidator表单校验、更改状态、新增、移除校验字段的实例代码
May 19 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
phpcms中的评论样式修改方法
2016/10/21 PHP
PHP数组中头部和尾部添加元素的方法(array_unshift,array_push)
2017/04/10 PHP
php如何计算两坐标点之间的距离
2018/12/29 PHP
php策略模式简单示例分析【区别于工厂模式】
2019/09/25 PHP
JQuery 引发两次$(document.ready)事件
2010/01/15 Javascript
javascript获取隐藏dom的宽高 具体实现
2013/07/14 Javascript
JS实现网页背景颜色与select框中颜色同时变化的方法
2015/02/27 Javascript
jquery表单对象属性过滤选择器实例分析
2015/05/18 Javascript
jQuery解析XML文件同时动态增加js文件的方法
2015/06/01 Javascript
JS实现生成会变大变小的圆环实例
2015/08/05 Javascript
探究JavaScript函数式编程的乐趣
2015/12/14 Javascript
在javascript中创建对象的各种模式解析
2016/05/16 Javascript
JS中跨页面调用变量和函数的方法(例如a.js 和 b.js中互相调用)
2016/11/01 Javascript
新闻上下滚动jquery 超简洁(必看篇)
2017/01/21 Javascript
JavaScrpt的面向对象全面解析
2017/05/09 Javascript
ReactNative之FlatList的具体使用方法
2017/11/29 Javascript
vue中子组件的methods中获取到props中的值方法
2018/08/27 Javascript
[44:40]Spirit vs Navi Supermajor小组赛 A组败者组第一轮 BO3 第一场 6.2
2018/06/03 DOTA
python中的全局变量用法分析
2015/06/09 Python
Django REST framework 如何实现内置访问频率控制
2019/07/23 Python
解决pyCharm中 module 调用失败的问题
2020/02/12 Python
用gpu训练好的神经网络,用tensorflow-cpu跑出错的原因及解决方案
2021/03/03 Python
Oasis服装官网:时尚女装在线
2020/07/09 全球购物
J2SDK1.5与J2SDK5.0有什么区别
2012/09/19 面试题
保卫钓鱼岛口号
2014/06/20 职场文书
维护民族团结演讲稿
2014/08/27 职场文书
工商局副局长个人对照检查材料
2014/09/25 职场文书
党员贯彻十八大精神思想汇报范文
2014/10/25 职场文书
2014年乡镇卫生院工作总结
2014/11/24 职场文书
建议书格式
2015/02/04 职场文书
酒店收银员岗位职责
2015/04/07 职场文书
个人合作协议范本
2015/08/06 职场文书
2016年中秋节慰问信
2015/12/01 职场文书
linux下导入、导出mysql数据库命令的实现方法
2021/05/26 MySQL
Python函数中的不定长参数相关知识总结
2021/06/24 Python
vue实现input输入模糊查询的三种方式
2022/08/14 Vue.js