2013-02-01 127 views
2

我正在为地图创建群集功能(v2)。我组位置成集群,然后显示集群为自定义标记:Android Maps v2 - 动画标记

enter image description here

这个伟大的工程,但我想创建一个动画获得创建群集时和分裂。我通过在标记(注释)上创建一个UIView动画来成功地完成了这个任务。我找不到任何代码/提示在线为Android。

我设法得到一个简单的ImageView作为叠加,以类似于一个簇,然后使用TranslateAnimation来获得所需的动画。最后,我删除了这个视图并添加了标记。

是否有更好的方法来标记动画?

+0

你是如何让这个圆圈变大的?或者你给它一个半径的大值? – mr5

+0

这是一个自定义视图。集群中位置越多,半径越大。 –

+0

你如何定义它的大小?你在谷歌地图内绘制这些圈子吗? – mr5

回答

0

我发现了一个solution的作品:

final LatLng target = NEW_LOCATION; 

final long duration = 400; 
final Handler handler = new Handler(); 
final long start = SystemClock.uptimeMillis(); 
Projection proj = map.getProjection(); 

Point startPoint = proj.toScreenLocation(marker.getPosition()); 
final LatLng startLatLng = proj.fromScreenLocation(startPoint); 

final Interpolator interpolator = new LinearInterpolator(); 
handler.post(new Runnable() { 
    @Override 
    public void run() { 
     long elapsed = SystemClock.uptimeMillis() - start; 
     float t = interpolator.getInterpolation((float) elapsed/duration); 
     double lng = t * target.longitude + (1 - t) * startLatLng.longitude; 
     double lat = t * target.latitude + (1 - t) * startLatLng.latitude; 
     marker.setPosition(new LatLng(lat, lng)); 
     if (t < 1.0) { 
      // Post again 10ms later. 
      handler.postDelayed(this, 10); 
     } else { 
      // animation ended 
     } 
    } 
}); 

这是一个有点慢约20同时,也许有更好的办法?

+3

由于Marker的每次更改都涉及IPC回到Play Services Framework应用程序,我怀疑它会变得更好,并且可能会很多更差。 – CommonsWare

8

通过动画标记对象而不是添加和删除GoogleMap前面的视图,您正处于正确的轨道,但如果使用Animator对象为标记设置动画效果,则可以获得更好的性能。

使用Handler和延迟Runnable方法,您可以有效地对目标帧速率进行硬编码。如果以过低的延迟发布Runnable,则您的动画执行时间会较长。如果帧率过高,帧速率会太慢,即使在强大的设备上也会显得不稳定。在处理程序上使用Animator并延迟Runnable的好处是它只会调用onAnimationUpdate()以便像系统可以处理的那样频繁地绘制下一帧。

在我的群集库Clusterkraf中,我使用ObjectAnimator(从NineOldAndroids向后兼容)在更改缩放级别时为群集转换设置动画。它可以在我的Galaxy Nexus上顺畅地动画100个标记。

下面是关于如何完成这项工作的摘要。

class ClusterTransitionsAnimation implements AnimatorListener, AnimatorUpdateListener { 

    private ObjectAnimator animator; 
    private AnimatedTransitionState state; 
    private ClusterTransitions transitions; 
    private Marker[] animatedMarkers; 

    void animate(ClusterTransitions transitions) { 
     if (this.state == null) { 
      Options options = optionsRef.get(); 
      Host host = hostRef.get(); 
      if (options != null && host != null) { 
       this.state = new AnimatedTransitionState(transitions.animated); 
       this.transitions = transitions; 
       animator = ObjectAnimator.ofFloat(this.state, "value", 0f, 1f); 
       animator.addListener(this); 
       animator.addUpdateListener(this); 
       animator.setDuration(options.getTransitionDuration()); 
       animator.setInterpolator(options.getTransitionInterpolator()); 
       host.onClusterTransitionStarting(); 
       animator.start(); 
      } 
     } 
    } 

    @Override 
     public void onAnimationStart(Animator animator) { 
      // Add animatedMarkers to map, omitted for brevity 
     } 

    @Override 
    public void onAnimationUpdate(ValueAnimator animator) { 
     if (state != null && animatedMarkers != null) { 
      LatLng[] positions = state.getPositions(); 
      for (int i = 0; i < animatedMarkers.length; i++) { 
       animatedMarkers[i].setPosition(positions[i]); 
      } 
     } 
    } 
} 
+0

听起来很有希望,我会为下一个版本尝试。谢谢! –

2

下面的代码是正确的,但我会puntualize的东西。我会用16毫秒== 60fps。人眼不能分辨小于16毫秒,所以:

final LatLng target = NEW_LOCATION; 

final long duration = 400; 
final Handler handler = new Handler(); 
final long start = SystemClock.uptimeMillis(); 
Projection proj = map.getProjection(); 

Point startPoint = proj.toScreenLocation(marker.getPosition()); 
final LatLng startLatLng = proj.fromScreenLocation(startPoint); 

final Interpolator interpolator = new LinearInterpolator(); 
handler.post(new Runnable() { 
    @Override 
    public void run() { 
     long elapsed = SystemClock.uptimeMillis() - start; 
     float t = interpolator.getInterpolation((float) elapsed/duration); 
     double lng = t * target.longitude + (1 - t) * startLatLng.longitude; 
     double lat = t * target.latitude + (1 - t) * startLatLng.latitude; 
     marker.setPosition(new LatLng(lat, lng)); 
     if (t < 1.0) { 
      // Post again 16ms later == 60 frames per second 
      handler.postDelayed(this, 16); 
     } else { 
      // animation ended 
     } 
    } 
}); 
相关问题