2013-02-01 184 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 
     } 
    } 
}); 
相關問題