Smooth zoom in mapview
When I use MapController.setZoom(x) and, for instance, zoom from level 5 to 15 the zoom is perform very fast and often the map tiles of the new level are not loaded.
This does not look so good to the user. Any Maps build in function to change this to a more slow zoom so tiles can be loaded, or at least almost loaded, before level 15 is reached?
Best rega开发者_如何学Pythonrds
P
A simpler way is to take advantage of the MapController.zoomIn() method that provides some simple animation for zooming a step level.
Here's some code:
// a Quick runnable to zoom in
int zoomLevel = mapView.getZoomLevel();
int targetZoomLevel = 18;
long delay = 0;
while (zoomLevel++ < targetZoomLevel) {
handler.postDelayed(new Runnable() {
@Override
public void run() {
mapController.zoomIn();
}
}, delay);
delay += 350; // Change this to whatever is good on the device
}
What it does is create a sequence of delayed runnables each one of which will call zoomIn() 350ms after the previous one.
This assumes that you have a Handler attached to your main UI thread called 'handler'
:-)
There's no simple way to do this. However, I can help you out.
Firstly, here's a free gift of one of my personal utility classes, Tween.java:
import android.os.Handler;
public class Tween {
public static interface TweenCallback {
public void onTick(float time, long duration);
public void onFinished();
}
long start;
long duration;
Handler handler;
TweenCallback callback;
public Tween(TweenCallback callback) {
handler = new Handler();
this.callback = callback;
}
public void start(final int duration) {
start = android.os.SystemClock.uptimeMillis();
this.duration = duration;
tickRunnable.run();
}
public void stop() {
handler.removeCallbacks(tickRunnable);
}
Runnable tickRunnable= new Runnable() {
public void run() {
long now = android.os.SystemClock.uptimeMillis();
float time = now - start;
boolean finished = (time >= duration);
if (finished) {
time = duration;
}
callback.onTick(time, duration);
if (!finished) {
handler.post(tickRunnable);
}
else {
callback.onFinished();
}
}
};
//
// Tweening functions. The 4 parameters are :
//
// t - time, ranges from 0 to d
// b - begin, i.e. the initial value for the quantity being changed over time
// c - change, the amount b will be changed by at the end
// d - duration, of the transition, normally in milliseconds.
//
// All were adapted from http://jstween.sourceforge.net/Tween.js
//
public static float strongEaseInOut(float t, float b, float c, float d) {
t/=d/2;
if (t < 1) return c/2*t*t*t*t*t + b;
return c/2*((t-=2)*t*t*t*t + 2) + b;
}
public static float regularEaseIn(float t, float b, float c, float d) {
return c*(t/=d)*t + b;
}
public static float strongEaseIn(float t, float b, float c, float d) {
return c*(t/=d)*t*t*t*t + b;
}
}
What I recommend you do is use MapController.zoomToSpan()
in conjunction with a Tween... here's some completely untested code that should work, maybe with a tweak or two, you just pass it the target lat & lon spans. :
public void slowZoom(int latE6spanTarget, int lonE6spanTarget) {
final float initialLatE6span = mapView.getLatitudeSpan();
final float initialLonE6span = mapView.getLongitudeSpan();
final float latSpanChange = (float)(latE6spanTarget - initialLatE6span);
final float lonSpanChange = (float)(lonE6spanTarget - initialLonE6span);
Tween tween = new Tween(new Tween.TweenCallback() {
public void onTick(float time, long duration) {
float latSpan = Tween.strongEaseIn(time, initialLatE6span, latSpanChange, duration);
float lonSpan = Tween.strongEaseIn(time, initialLonE6span, lonSpanChange, duration);
mapView.getController().zoomToSpan((int)latSpan, (int)lonSpan);
}
public void onFinished() {
}
});
tween.start(5000);
}
精彩评论