我正在为地图创建群集功能(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