使用高德地图实现点平滑移动-优化版

高德地图中有可供调用的 点平滑移动 的 API,但是功能相对简单,不足以满足项目需求。
故多方寻求方案,未果!只能自己动手实现,现在贴出来和大家一起分享。

转载请注明出处:www.facex.xyz,如有发现错误或有其他更好的实现方式可与我联系。

首先声明,通过本文不一定能解决你所面临的问题,关键在于理解其实现原理,尤其是第3点:高德官方点平滑移动API实现过程。

1. 原有方案介绍

之前有写过一篇 使用高德地图模拟运动轨迹, 介绍了使用高德地图的点平滑移动 API 来实现模拟运动轨迹,但是存在几个问题:

  1. 一旦设置了动画时间并开始动画,只有停止选项,然后就没有然后了。
  2. 不支持在轨迹上任意位置暂停,高德 API 的动画只能在轨迹的经纬度数组中的点停止,当调用停止动画时,而点还没有到达经纬度数组中的点的位置,这时点会继续向前走(而不是马上停止),直到到达数组中下一个经纬度点上。
  3. 不支持以速度来驱动动画,并在动画过程中改变速度。

2. 优化方案介绍

针对上面的 3 个问题,本次分享的点平滑移动方案优化如下:

  1. 支持暂停和继续。
  2. 支持在任意时刻,任意位置暂停。
  3. 支持以速度来驱动动画,并且支持动画中改变速度。

下面开始我的分享:

3. 高德官方点平滑移动API实现过程

高德地图开源了点平滑移动 API 的技术实现, 我的优化也是建立在此基础之上的。

开源地址:android-smooth-move

文档地址:点平滑移动

我大概分析下其实现过程:

  1. 计算轨迹经纬度数组每两个点的距离
  2. 然后对每两个点之间的直线路径做 TranslateAnimation 动画,本段动画时间 = 动画总时间 * 本短距离 / 路径总距离
  3. 在一段动画结束后开始下一段动画,直到路径结束

其实质是对高德 3D 地图做了一个封装,具体的代码实现可以参考源码。

4. 优化方案要点讲解

下面是我的优化方案, 只贴部分代码,具体实现细节也请参考源码。

项目地址:SmoothMove

4.1 以速度驱动动画

在两点之间做 ValueAnimator 时,根据两点之间的距离,计算本次动画需要的时间,本段动画时间 = 本段距离 / 速度。

      
      
1
2
      
      
final double dis = eachDistance.poll();
final long time = ( long) (dis / speed * 60 * 60);

4.2 在任意时刻,任意点暂停

我修改了动画的实现方式,改用 ValueAnimator,通过实现 TypeEvaluator 自定义 LngLatEvaluator 类,使动画过程中返回当前点的经纬度值 LngLat。调用 ValueAnimator 的 cancel() 方法,动画即停止。此时可以取到当前点的坐标点。

      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
      
      
LatLng curPos = marker.getPosition();
nextPos = points.poll();
final LngLat curLngLat = new LngLat(curPos.longitude, curPos.latitude);
LngLat nextLngLat = new LngLat(nextPos.longitude, nextPos.latitude);
markerAnimator = ValueAnimator.ofObject( new LngLatEvaluator(), curLngLat,
nextLngLat);
markerAnimator.setDuration(time);
markerAnimator.setInterpolator( new LinearInterpolator());
markerAnimator.addUpdateListener( new ValueAnimator.AnimatorUpdateListener() {
public void (ValueAnimator animation) {
LngLat lngLat = (LngLat) animation.getAnimatedValue();
}
});

4.3 暂停和继续

暂停时先取消当前动画

      
      
1
2
3
4
5
6
7
      
      
public void pauseMove() {
if (animStop) {
return;
}
animStop = true;
markerAnimator.cancel();
}

在动画取消的回调中重新计算剩余路径的经纬度数组

      
      
1
2
3
4
5
6
      
      
public void onAnimationCancel(Animator animation) {
animCancel = true;
points.addFirst(nextPos);
double newDistance = AMapUtils.calculateLineDistance(marker.getPosition(), points.get( 0));
eachDistance.addFirst(newDistance);
}

继续时对重新计算剩余的路径做动画。

      
      
1
2
3
4
5
6
7
      
      
public void resumeMove() {
if (!animStop) {
return;
}
animStop = false;
startRun();
}

4.4 改变平滑移动的速度

改变平滑移动的速度,需要用到暂停的继续功能,当改变速度时,先暂停当前动画,然后对动画的速度变量赋新值,最后继续动画。

      
      
1
2
3
4
5
      
      
public void changeSpeed(float speed) {
pauseMove();
this.speed = speed;
resumeMove();
}

4.5 回调平滑移动的累计移动距离和总距离

动画中回调平滑移动的累计移动距离和总距离,方便计算当前进度等。

回调的总距离不等同于路径规划的距离,相对于路径规划距离的不准确性,回调的总距离可视为精确距离(至少对于地图上本次平滑移动),因为回调的总距离是每两点间距离累加所得。

大概就这么多了,三言两语也说不清,还是看代码吧。

原文:大专栏  使用高德地图实现点平滑移动-优化版


猜你喜欢

转载自www.cnblogs.com/petewell/p/11601781.html
今日推荐