百度地图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 相关文章推荐
查询绑定数据岛的表格中的文本并修改显示方式的js代码
Dec 15 Javascript
js下判断 iframe 是否加载完成的完美方法
Oct 26 Javascript
网页右键ie不支持event.preventDefault和event.returnValue (需要加window)
Feb 22 Javascript
JavaScript获取某年某月的最后一天附截图
Jun 23 Javascript
js实现横向百叶窗效果网页切换动画效果的方法
Mar 02 Javascript
JavaScript创建一个object对象并操作对象属性的用法
Mar 23 Javascript
jQuery实现选项卡功能(两种方法)
Mar 08 Javascript
JavaScript中的普通函数和箭头函数的区别和用法详解
Mar 21 Javascript
深度了解vue.js中hooks的相关知识
Jun 14 Javascript
vue 自动化路由实现代码
Sep 03 Javascript
vue之延时刷新实例
Nov 14 Javascript
JavaScript实现网页计算器功能
Oct 29 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使用codebase生成随机数
2014/03/25 PHP
PHP中file_get_contents高?用法实例
2014/09/24 PHP
laravel实现批量更新多条记录的方法示例
2017/10/22 PHP
Ajax中的JSON格式与php传输过程全面解析
2017/11/14 PHP
ext jquery 简单比较
2010/04/07 Javascript
jsTree 基于JQuery的排序节点 Bug
2011/07/26 Javascript
jQuery中live方法的重复绑定说明
2011/10/21 Javascript
javascript对话框使用方法(警告框 javascript确认框 提示框)
2014/01/07 Javascript
js中 javascript:void(0) 用法详解
2015/08/11 Javascript
jquery获取文档高度和窗口高度汇总
2016/01/25 Javascript
jquery实现表格中点击相应行变色功能效果【实例代码】
2016/05/09 Javascript
js实现控制textarea输入字符串的个数,鼠标按下抬起判断输入字符数
2016/10/25 Javascript
从0开始学Vue
2016/10/27 Javascript
Webpack打包慢问题的完美解决方法
2017/03/16 Javascript
Nodejs--post的公式详解
2017/04/29 NodeJs
原生实现一个react-redux的代码示例
2018/06/08 Javascript
express 项目分层实践详解
2018/12/10 Javascript
python实现排序算法
2014/02/14 Python
python学习之第三方包安装方法(两种方法)
2015/07/30 Python
python3实现TCP协议的简单服务器和客户端案例(分享)
2017/06/14 Python
Django使用list对单个或者多个字段求values值实例
2020/03/31 Python
python查找特定名称文件并按序号、文件名分行打印输出的方法
2020/04/24 Python
python中读入二维csv格式的表格方法详解(以元组/列表形式表示)
2020/04/24 Python
idea2020手动安装python插件的实现方法
2020/07/17 Python
如何在python中处理配置文件代码实例
2020/09/27 Python
Python collections模块的使用方法
2020/10/09 Python
css3 实现圆形旋转倒计时
2018/02/24 HTML / CSS
用html5绘制折线图的实例代码
2016/03/25 HTML / CSS
Pottery Barn阿联酋:购买家具、家居装饰及更多
2019/12/08 全球购物
马来西亚网上花店:FlowerAdvisor马来西亚
2020/01/03 全球购物
DOUGLAS波兰:在线销售香水和化妆品
2020/07/05 全球购物
美术专业学生个人自我评价
2013/09/19 职场文书
店长职务说明书
2014/02/04 职场文书
2016年小学感恩节活动总结
2016/04/01 职场文书
openGauss数据库JDBC环境连接配置的详细过程(Eclipse)
2022/06/01 Java/Android
Go 内联优化让程序员爱不释手
2022/06/21 Golang