什么是动画使用V2 API谷歌地图标记的最佳方式?
我在地图上为中心的游戏工作,我追踪的人的位置,并在地图上显示它们彼此看。 随人动,我想从他目前的一个标志动画,以他的最新位置。 每个人都有一个方向,所以我需要适当地旋转标记。
什么是做到这一点的最好办法使用新的谷歌地图API?
什么是动画使用V2 API谷歌地图标记的最佳方式?
我在地图上为中心的游戏工作,我追踪的人的位置,并在地图上显示它们彼此看。 随人动,我想从他目前的一个标志动画,以他的最新位置。 每个人都有一个方向,所以我需要适当地旋转标记。
什么是做到这一点的最好办法使用新的谷歌地图API?
一些谷歌工程师们提供了有关如何从起点动画标记到终点,为Android的所有不同版本的一些优雅的示例代码一个很好的演示视频:
相关的代码是在这里:
https://gist.github.com/broady/6314689
而在行动这一切的一个很好的演示视频。
http://youtu.be/WKfZsCKSXVQ
OLD DEPRECATED回答以下
在文档中,它被提及标记图标不能更改:
图标
在随即出现的标志的位图。 如果图标未设置,则显示默认图标。 您可以指定使用defaultMarker(浮动)的默认图标的替代着色。 一旦你创建的标记您不能更改的图标。
谷歌地图API第2版文档
你将不得不跟踪特定的标记,可能使用类似于这里所描述的方法: 链接标记到对象 ,然后找出哪些标记需要更新。 调用.remove()
上的标记,然后创建取决于“方向”旋转的图像需要,创建带有图像的新标记,新标记添加到地图。
你并不需要“明确”的地图,只需删除您要修改,创建一个新的标记,然后将其添加回地图。
不幸的是,新的地图API是不是很灵活呢。 希望谷歌继续在其改善。
用法示例 DiscDev的答案 (上图):
LatLng fromLocation = new LatLng(38.5, -100.4); // Whatever origin coordinates
LatLng toLocation = new LatLng(37.7, -107.7); // Whatever destination coordinates
Marker marker = mMap.addMarker(new MarkerOptions().position(firstLocation));
MarkerAnimation.animateMarkerToICS(marker, toLocation, new LatLngInterpolator.Spherical());
而对于那些你们谁使用GPS /或接收位置更新的任何位置提供:
Marker ourGlobalMarker;
// We've got a location from some provider of ours, now we can call:
private void updateMarkerPosition(Location newLocation) {
LatLng newLatLng = new LatLng(newLocation.getLatitude(), newLocation.getLongitude());
if(ourGlobalMarker == null) { // First time adding marker to map
ourGlobalMarker = mMap.addMarker(new MarkerOptions().position(newLatLng));
}
else {
MarkerAnimation.animateMarkerToICS(ourGlobalMarker, newLatLng, new LatLngInterpolator.Spherical());
}
}
重要:
在1MarkerAnimation.java
如果动画持续时间设置为X,并且是在较小的则X的速度接收位置更新,多个动画将被触发,你可能会看到标记动画闪烁了一下(这是不是一个很好的用户体验)。
为了避免这种情况, animationMarkerToICS
方法(我把这里animationMarkerToICS
为例),应该是这个样子,
全面方法实现:
private static Animator animator; // MAKING ANIMATOR GLOBAL INSTEAD OF LOCAL TO THE STATIC FUNCTION
...
// Ice Cream Sandwich compatible
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public static void animateMarkerToICS(Marker marker, LatLng finalPosition, final LatLngInterpolator latLngInterpolator) {
TypeEvaluator<LatLng> typeEvaluator = new TypeEvaluator<LatLng>() {
@Override
public LatLng evaluate(float fraction, LatLng startValue, LatLng endValue) {
return latLngInterpolator.interpolate(fraction, startValue, endValue);
}
};
Property<Marker, LatLng> property = Property.of(Marker.class, LatLng.class, "position");
// ADD THIS TO STOP ANIMATION IF ALREADY ANIMATING TO AN OBSOLETE LOCATION
if(animator != null && animator.isRunning()) {
animator.cancel();
animator = null;
}
animator = ObjectAnimator.ofObject(marker, property, typeEvaluator, finalPosition);
animator.setDuration((long) ANIMATION_DURATION);
animator.start();
}
请享用。
标记具有添加API V2的Rev.7号的新功能。 Marker.setIcon ,所以你可以使用多个图标显示方向。
//Your code
double bearing = 0.0;
bearing = getBearing(new LatLng(
currentPosition.latitude
,currentPosition.longitude),
new LatLng(
nextPosition.latitude,
nextPosition.longitude));
bearing -= 90;
CameraPosition cameraPosition = new CameraPosition
.Builder()
.target(new LatLng(nextPosition.latitude, nextPosition.longitude))
.bearing((float) bearing)
.zoom(ZOOM_LEVEL).build();
mGoogleMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition), 5000, null);
animatedMarker(currentPosition,nextPosition,busMarker);
//Method for finding bearing between two points
private float getBearing(LatLng begin, LatLng end) {
double lat = Math.abs(begin.latitude - end.latitude);
double lng = Math.abs(begin.longitude - end.longitude);
if (begin.latitude < end.latitude && begin.longitude < end.longitude)
return (float) (Math.toDegrees(Math.atan(lng / lat)));
else if (begin.latitude >= end.latitude && begin.longitude < end.longitude)
return (float) ((90 - Math.toDegrees(Math.atan(lng / lat))) + 90);
else if (begin.latitude >= end.latitude && begin.longitude >= end.longitude)
return (float) (Math.toDegrees(Math.atan(lng / lat)) + 180);
else if (begin.latitude < end.latitude && begin.longitude >= end.longitude)
return (float) ((90 - Math.toDegrees(Math.atan(lng / lat))) + 270);
return -1;
}
private void animatedMarker(final LatLng startPosition,final LatLng nextPosition,final Marker mMarker)
{
final Handler handler = new Handler();
final long start = SystemClock.uptimeMillis();
final Interpolator interpolator = new AccelerateDecelerateInterpolator();
final float durationInMs = 3000;
final boolean hideMarker = false;
handler.post(new Runnable() {
long elapsed;
float t;
float v;
@Override
public void run() {
// Calculate progress using interpolator
elapsed = SystemClock.uptimeMillis() - start;
t = elapsed / durationInMs;
v = interpolator.getInterpolation(t);
LatLng currentPosition = new LatLng(
startPosition.latitude * (1 - t) + nextPosition.latitude * t,
startPosition.longitude * (1 - t) + nextPosition.longitude * t);
mMarker.setPosition(currentPosition);
// Repeat till progress is complete.
if (t < 1) {
// Post again 16ms later.
handler.postDelayed(this, 16);
} else {
if (hideMarker) {
mMarker.setVisible(false);
} else {
mMarker.setVisible(true);
}
}
}
});
}