我正在爲地圖創建羣集功能(v2)。我組位置成集羣,然後顯示集羣爲自定義標記:Android Maps v2 - 動畫標記
這個偉大的工程,但我想創建一個動畫獲得創建羣集時和分裂。我通過在標記(註釋)上創建一個UIView動畫來成功地完成了這個任務。我找不到任何代碼/提示在線爲Android。
我設法得到一個簡單的ImageView作爲疊加,以類似於一個簇,然後使用TranslateAnimation
來獲得所需的動畫。最後,我刪除了這個視圖並添加了標記。
是否有更好的方法來標記動畫?
我正在爲地圖創建羣集功能(v2)。我組位置成集羣,然後顯示集羣爲自定義標記:Android Maps v2 - 動畫標記
這個偉大的工程,但我想創建一個動畫獲得創建羣集時和分裂。我通過在標記(註釋)上創建一個UIView動畫來成功地完成了這個任務。我找不到任何代碼/提示在線爲Android。
我設法得到一個簡單的ImageView作爲疊加,以類似於一個簇,然後使用TranslateAnimation
來獲得所需的動畫。最後,我刪除了這個視圖並添加了標記。
是否有更好的方法來標記動畫?
我發現了一個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同時,也許有更好的辦法?
由於Marker的每次更改都涉及IPC回到Play Services Framework應用程序,我懷疑它會變得更好,並且可能會很多更差。 – CommonsWare
通過動畫標記對象而不是添加和刪除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]);
}
}
}
}
聽起來很有希望,我會爲下一個版本嘗試。謝謝! –
下面的代碼是正確的,但我會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
}
}
});
你是如何讓這個圓圈變大的?或者你給它一個半徑的大值? – mr5
這是一個自定義視圖。集羣中位置越多,半徑越大。 –
你如何定義它的大小?你在谷歌地圖內繪製這些圈子嗎? – mr5