仿滴滴打车的平滑移动附近车辆效果实现全流程,基于高德地图
2017-03-18 11:46
627 查看
源码地址:https://github.com/zyktojo/AmapSmoothMarker
欢迎Star~~
开端:
打开滴滴打车APP,会发现地图上的车辆显示的十分形象,车辆会在路上平滑的加减速,转向停车~有种即时战略的感觉,看起来挺有趣:
为了研究这个效果如何实现,我开始了探索之旅:
一.探索阶段:
1.旧版平滑移动
首先找到的是百度“高德地图平滑移动”结果里的这个文:http://lbs.amap.com/smart/transportation/skill/move/
实现方式是开启子线程,不断执行绘制-销毁图标marker方法来实现看起来在不断向前移动的动画:
于是下载了这个DEMO,跑起来,发现确实移动效果不错
但是!!
问题是这个实现方式很难支持多点同时移动
经过实践发现使用这个方法同时操纵多marker时,很大概率只能成功移动最后操作的那个marker,而之前的所有marker都一动不动
努力改造两天之后,依然没有成功保证所有该动的marker都动起来,因此决定另寻他路
2.新版移动
运气还不错,在高德官方文档里找到了17年刚刚发布的新文档:http://lbs.amap.com/api/android-sdk/guide/draw-on-map/smooth-move
简单浏览了一下这个新文档和DEMO,发现这个实现方式明显封装更良好,也更能保证线程和内存安全
二.开始实现
1.下载最新版Jar包:4.1.3
要想实现这个,必须使用最新版的高德地图SDK,即4.1.3以上版本在Gradle修改版本,刷新Gradle,搞定
2.会移动的Mark类:SmoothMoveMarker
先看看官方实现的逻辑代码:// 获取轨迹坐标点 List<LatLng> points = readLatLngs(); LatLngBounds bounds = new LatLngBounds(points.get(0), points.get(points.size() - 2)); mAMap.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 50)); SmoothMoveMarker smoothMarker = new SmoothMoveMarker(mAMap); // 设置滑动的图标 smoothMarker.setDescriptor(BitmapDescriptorFactory.fromResource(R.drawable.icon_car)); LatLng drivePoint = points.get(0); Pair<Integer, LatLng> pair = SpatialRelationUtil.calShortestDistancePoint(points, drivePoint); points.set(pair.first, drivePoint); List<LatLng> subList = points.subList(pair.first, points.size()); // 设置滑动的轨迹左边点 smoothMarker.setPoints(subList); // 设置滑动的总时间 smoothMarker.setTotalDuration(40); // 开始滑动 smoothMarker.startSmoothMove();[/code]
发现高德新增了一个支持移动的Marker类:
SmoothMoveMarker
只要放入轨迹,设定好滑动时间,他就会愉快的滑动起来啦~
3.初步实现多Marker移动
阅读高德demo源码,发现他封装了两个方法来实现移动,一个是移动,另一个是读取路线坐标值://平滑移动 public void movePoint() { // 获取轨迹坐标点 List<LatLng> points = readLatLngs(); LatLngBounds bounds = new LatLngBounds(points.get(0), points.get(points.size() - 2)); aMap.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 50)); SmoothMoveMarker smoothMarker = new SmoothMoveMarker(aMap); // 设置滑动的图标 smoothMarker.setDescriptor(BitmapDescriptorFactory.fromResource(R.drawable.car_up)); LatLng drivePoint = points.get(0); Pair<Integer, LatLng> pair = SpatialRelationUtil.calShortestDistancePoint(points, drivePoint); points.set(pair.first, drivePoint); List<LatLng> subList = points.subList(pair.first, points.size()); // 设置滑动的轨迹左边点 smoothMarker.setPoints(subList); // 设置滑动的总时间 smoothMarker.setTotalDuration(10); // 开始滑动 smoothMarker.startSmoothMove(); } //获取路线 private List<LatLng> readLatLngs() { List<LatLng> points = new ArrayList<LatLng>(); for (int i = 0; i < coords.length; i += 2) { points.add(new LatLng(coords[i + 1], coords[i])); } return points; }
为了观察多点同时移动,决定把这个方法重复实现两次,两条路线不一样
那怎么设定不同的路线呢?
readLatLngs():这个方法读取了名为coords的集合
那么我们就先设定一个deuble[]集合
把路线经过点的各个坐标值放进去
第二次运行的时候再改变这个集合就OK了~
如下例,地图中心点是天安门,两辆车会从天安门西边,一个向南一个向北移动:
double[] newoords = {116.380729, 39.906443, 116.330776, 39.868508}; coords = newoords; movePoint(); double[] newoords2 = {116.319618, 39.929614, 116.437377, 39.906443}; coords = newoords2; movePoint();
经过试验,可以良好的支持多点同时移动
——————————————基础实现部分到这里为止,接下来是具体业务开发相关————————————————
4.加入路线,刷新
搞定了基础实现,接下来就要考虑具体场景了1.数据源:
由于司机端的数据源信息更新慢(每10秒报一轮GPS),方向信息缺乏(静止时没有方向数据)考虑到这些原因,我决定把平滑移动的时间改为10秒:
// 设置滑动的总时间 smoothMarker.setTotalDuration(10);
查询附近车辆的接口,也改为每十秒钟循环一次,以达到与司机端发送信息的频率一致
carsHandler.postDelayed(this, 10000);
2.对照车辆ID
如何判断新得到的那些车,有哪几辆是与上次搜索时一样的呢?首先,必须有车辆ID
看看接口文档,接口数据里除了经纬度之外还带了个car_id,果断拿来对照一下
具体实现时要考虑两种情况:
1.如果car_id相同:平滑移动marker
2.如果car_id不同:展示静态marker
5.问题:如何清除旧marker?
很简单,每次成功请求到新的附近车辆数据时,把AMap对象clear()一下就行咯缺点是会有瞬间的地图闪动,那一瞬间地图上所有附加的图标点全部清空,不过时间很短不太容易察觉到
效果展示:
三.优化
1.第一次加载时的角度
在写完上述功能后,发现一个问题:车辆第一次加载在地图上时,marker的角度全都是默认角度:0度,头朝上
这可不太友好,于是问了问司机端,能不能获取一下即时的车辆角度?
回答是:动的时候可以,静止之后不能
于是又问了服务端,能不能做一个“记录车辆最后一次报告的角度”功能
这个当然可以~
于是完美解决了第一次加载车辆marker时的角度问题
2.地图挪动时,太灵敏
解决了角度问题,又发现一个新的问题,就是“地图中心点改变时,如何即时刷新附近车辆?”高德地图的API给出的监听方法是:
onCameraChangeFinish()
用来在地图被挪动后执行一些方法
之前一直把获取附近车辆的接口方法写在这里,因而造成了:
即使地图只挪了1米远,同样会发出一遍获取附近车辆的请求
这样造成的坏处是:
1.增加服务器负担
2.影响正常marker动画展示,因为前后两次请求如果小于10秒,那么请求到的坐标值是一样的,这样的话车辆就不会移动了
一个简单的解决方案是:
把“请求附近车辆”的方法放进界面onCreate()或者onResume()方法里,用Hnadler继承runnable接口的方式写一个循环执行的线程
这样解决了地图挪动太灵敏的问题,不过也造成了地图挪动后,新位置附近的车加载过慢的新问题
要解决这个也很简单,刚才说到的onCameraChangeFinish()方法,可以在这个方法里销毁一下刚才的Handler并且重新post()一遍就行啦~
哎不对,这岂不是跟刚开始的时候一样了嘛?
淡定,这一步还没做完,我们可以对比一下地图前后中心点的距离,当它大于某个长度后才进行搜索嘛~
这样每次地图挪动之后都会重新执行一下“加载附近车辆”的方法,同时又不用担心加载过于灵敏或者线程重复执行的问题啦
3.渐变展现
在快要完成这项功能的最后,我发现滴滴的车辆展示其实不是立马展示上去的,而是有一个渐隐动画我决定也做一个类似的效果
用到了经典的安卓动画文件夹:anim
里面可以设定透明度:alpha:
还可以设定展示的时间during:
设定好参数之后呢,在java文件里加载也很方便,
让指定的marker对象:.startAnimation(animationutils.loadanimation(R.anim.xxx_xx));
大功告成~
效果展示:
相关文章推荐
- 基于jquery的从一个页面跳转到另一个页面的指定位置的实现代码(带平滑移动的效果)
- OC-高德地图-附近的车-车辆平滑移动总结
- Android 滴滴打车,打车软件客户端实现小车在地图上平滑移动的实现;基于高德地图V4.1.1+
- ANDROID GridView 分页平滑滑动 效果的实现(基于android TV遥控器操作)
- Unity 实现类似 QQ泡泡堂一样平滑行走的 基于Tile的移动算法
- 基于jquery实现左右上下移动效果
- 移动网络游戏实现流程 -- 基于Cocos2d-x引擎和pomelo服务器框架
- 类似滴滴打车,多辆小车在地图上平滑移动的实现,基于百度地图实现(无轨迹)
- 基于JS实现带动画效果的流程进度条
- 基于HTML5陀螺仪实现ofo首页眼睛移动效果
- Python基于pygame实现图片代替鼠标移动效果
- 类似滴滴打车,多辆小车在地图上平滑移动的实现,基于百度地图实现(轨迹已画好)
- Android滴滴这种附近车辆运行效果怎么实现啊
- 实现qq ipad客户端的对话框平滑移动的效果
- 滴滴打车,打车软件app实现。小车在地图上平滑移动的实现,Android,基于高德地图开发实现
- 与viewpager联动实现其他view平滑移动效果
- [置顶] 基于高德地图实现Marker聚合效果
- 类似滴滴打车,多辆小车在地图上平滑移动的实现,基于百度地图实现(无轨迹)
- 基于高德地图实现移动互联网地图定位自动检索系统