Google Maps v2 上的动画标记
Posted
技术标签:
【中文标题】Google Maps v2 上的动画标记【英文标题】:Animating markers on Google Maps v2 【发布时间】:2013-01-29 15:43:14 【问题描述】:使用 v2 API 在 Google 地图上制作动画标记的最佳方式是什么?
我正在开发一款以地图为中心的游戏,我可以在其中跟踪人们的位置并将他们显示在地图上以供彼此查看。当人们移动时,我想将一个标记从他的当前位置设置为他的最新位置。每个人都有一个方向,所以我需要适当地旋转标记。
使用新的 Google Maps API 最好的方法是什么?
【问题讨论】:
可能duplicate?如果在您选择的解决方案中,您需要插入经度,请密切注意在 180 经线处翻转的标志。 @hleinone 不完全。您提到的解决方案有 a) 移动相机 b) 将标记移动到不同位置。我需要 b),它可以通过简单地做 Marker.setPosition() 来完成。但是,更改标记的图标(我将显示沿移动方向旋转的图像)不起作用。看来,需要清除地图上的所有标记才能更改图标。 用于动画折线路线github.com/amalChandran/google-maps-route-animation 【参考方案1】:一些 Google 工程师提供了一个很好的演示视频,其中包含一些优雅的示例代码,说明如何为所有不同版本的 android 设置从起点到终点的动画标记:
相关代码在这里:
https://gist.github.com/broady/6314689
还有一个很好的演示视频,展示了所有这些操作。
http://youtu.be/WKfZsCKSXVQ
以下已弃用的旧答案
在文档中提到不能更改标记图标:
图标
为标记显示的位图。如果未设置图标,则会显示默认图标。您可以使用 defaultMarker(float) 指定默认图标的替代颜色。 创建标记后,您将无法更改图标。
Google Maps API v2 Documentation
您将不得不跟踪特定标记,可能使用类似于此处描述的方法:Link a Marker to an Object,然后找出您需要更新的标记。在标记上调用.remove()
,然后根据您想要的“方向”创建旋转图像,使用该图像创建新标记,并将新标记添加到地图中。
您不需要“清除”地图,只需删除要修改的标记,创建一个新标记,然后将其添加回地图。
很遗憾,新的 Maps API 还不是很灵活。希望 Google 继续改进它。
【讨论】:
@Ted - 我做了一些搜索,找到了一个“真实”的答案并更新了我的帖子。看看上面,它非常简洁易懂。【参考方案2】:完整示例为DiscDev's answer(上):
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();
享受吧。
【讨论】:
我们如何设置缩放级别? 缩放与此问题无关,请查看here进行缩放 我收到以下错误:android.util.NoSuchPropertyException: No accessor method or field found for property with name position【参考方案3】:Marker 在 API v2 的 rev.7 中添加了一个新功能。 Marker.setIcon,所以你可以使用多个图标来显示方向。
【讨论】:
你试过用 setIcon 制作动画吗?就我而言,有时眨眼很糟糕(太快或太慢)...... @aat 我知道它仍然存在问题。毕竟是IPC调用。也许 Google 员工可以像 ios 一样添加真正的动画支持。【参考方案4】: //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);
);
【讨论】:
我用过这段代码。但我得到了多个标记。当汽车移动时,较旧的标记不会隐藏。你能告诉我如何正确使用这个“hideMarker”值吗?以上是关于Google Maps v2 上的动画标记的主要内容,如果未能解决你的问题,请参考以下文章
Google Maps Android API v2 - 检测地图上的触摸
Google Maps Android API v2,错误的标记位置