【问题标题】:Smooth zoom in mapview平滑放大地图视图
【发布时间】:2011-05-22 20:31:49
【问题描述】:

当我使用 MapController.setZoom(x) 并且,例如,从 5 级缩放到 15 级时,缩放执行得非常快,并且通常不会加载新级别的地图图块。

这对用户来说看起来不太好。是否有任何地图内置功能可以将其更改为更慢的缩放,以便在达到 15 级之前加载或至少几乎加载图块?

最好的问候

P

【问题讨论】:

  • 动画速度有一个很大的优势:减少了无用加载图像的数量。当使用@1ka 和@Reuben 提供的示例时,它会导致(可能的)3G/UMTS 网络上的大量位图加载调用在 350 毫秒后被丢弃。那是对带宽的浪费,有时甚至是来自用户的纯钱。还要注意的是,即使 pc 浏览器中的谷歌地图也是这样工作的,每个人都习惯了。没有人期望在切换显示位置时地图已经加载。

标签: android google-maps zooming


【解决方案1】:

更简单的方法是利用 MapController.zoomIn() 方法,该方法提供了一些简单的动画来缩放步进级别。

这里有一些代码:

    // 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
    }

它所做的是创建一系列延迟的可运行程序,每个可运行程序将在前一个运行程序之后 350 毫秒调用 zoomIn()。

这假设您有一个附加到您的主 UI 线程的处理程序,称为“处理程序”

:-)

【讨论】:

  • 您还可以在接近 18 级时添加更大的延迟,以产生减速的感觉。
  • 关于 WarrenFaith 对带宽的评论,那么上面与用户使用屏幕上的按钮手动放大和缩小没有什么不同。随着 350 的延迟,我得到连续缩放,但没有渲染图像。我认为 MapView 足够聪明,可以等到所有活动都停止后再请求图块。但肯定是 IDK。
【解决方案2】:

没有简单的方法可以做到这一点。不过,我可以帮你。

首先,这是我个人实用程序类之一的免费礼物,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;
    }
}

我建议您将MapController.zoomToSpan() 与 Tween 结合使用...这里有一些完全未经测试的代码应该可以工作,也许只需进行一两次调整,您只需将目标 lat & lon 跨度传递给它。 :

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);
}

【讨论】:

  • 谢谢鲁本!我已经尝试过了,但是在每个滴答声中(在 onTick() 回调中)它不会更新地图视图,我认为这种方法会执行 mapView.getController().zoomToSpan((int)latSpan, (int)lonSpan);现在它在手机中看起来像是暂停了 5 秒,然后缩放到最后一个级别。有什么想法吗?
  • 哦,见鬼,我敢打赌 zoomToSpan 会启动它自己的动画……这很烦人。非常抱歉。如果您可以立即设置浮点缩放级别,它就会起作用……奇怪的是 Google 地图类有多弱。
猜你喜欢
  • 2016-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-25
相关资源
最近更新 更多