在地图视图上平滑地动画演示相机路径

11

我正在使用地图视图(MapView)(新API V2版本)来展示一条路线上的点,这些点非常接近。我的问题是,当我调用动画步骤时:

        mMapInstance.animateCamera(CameraUpdateFactory.newLatLng(mNextPosition),ms, null);

摄影师的行为像一只勇敢无畏的蚱蜢,过程中举重若轻地进行夸张的拍摄,导致所有的幻灯片缓存都 @##@#@#!

如何最好地动画化路径并实现统一的滚动体验?速度不是问题,我会使用低速,我只关心流畅度...

如果我可以模拟我用手指画的路径就好了...因为地图表现得很棒,并且周围有很多瓷砖缓存。但是任何尝试以编程方式移动地图都会导致粗糙的动画、白屏和重新加载瓷砖...

提前感谢!!!

2个回答

4

我发现将可选回调函数作为递归解决方案的最后一个参数使用可以提供平滑的动画效果。以下代码实现了缩放、全景旋转角度变化,然后再次缩放;但是当初始参数和初始回调函数相同时,它会出现问题;我相信有更好的方法来调用递归,但是希望这可以给你一些关于如何实现函数动画的想法:

    //initial zoom
static final int initZoom = 8;
//steps the zoom
int stepZoom = 0;
// number of steps in zoom, be careful with this number!
int stepZoomMax = 5;
//number of .zoom steps in a step
int stepZoomDetent = (18 - initZoom) / stepZoomMax;
//when topause zoom for spin
int stepToSpin = 4;
//steps the spin
int stepSpin = 0;
//number of steps in spin (factor of 360)
int stepSpinMax = 4;
//number of degrees in stepSpin
int stepSpinDetent = 360 / stepSpinMax;

Intent detailIntent;
Intent intent;  
Marker marker;
final int mapHopDelay = 2000;

@Override
public void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.map_affirm);
    try
    {MapsInitializer.initialize(this);}
    catch (GooglePlayServicesNotAvailableException impossible)
    {   /* Impossible */ Log.e(TAG, "the impossible occurred");}
    intent = this.getIntent();
    latLng = new LatLng(intent.getDoubleExtra("Latitude", 0.0), intent.getDoubleExtra("Longitude", 0.0));
    map = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();
    map.animateCamera(CameraUpdateFactory.newCameraPosition(CameraPosition.builder()
                                                            .target(latLng)
                                                            .zoom(initZoom-1)
                                                            .build())
                      , mapHopDelay
                      , cameraAnimation
                      );
    marker = map.addMarker(new MarkerOptions()
                           .draggable(true)
                           .position(latLng)
                           .title("Location of Photographer"));

}

public CancelableCallback cameraAnimation = new CancelableCallback(){

    @Override
    public void onFinish()
    {
        if (stepZoom < stepZoomMax && stepZoom != stepToSpin)
        {
            stepZoom++;
            map.animateCamera(CameraUpdateFactory.newCameraPosition(CameraPosition.builder()
                                                                    .target(latLng)
                                                                    .zoom(initZoom + (stepZoomDetent * (stepZoom - 1)))
                                                                    //   .bearing(40*aniStep)
                                                                    //   .tilt(60)
                                                                    .build()), mapHopDelay, cameraAnimation);

        }
        else if (stepZoom >= stepZoomMax)// ending position hard coded for this application
        {map.animateCamera(CameraUpdateFactory.newCameraPosition(CameraPosition.builder()
                                                                 .target(latLng)
                                                                 .zoom(18)
                                                                 //  .bearing(0)
                                                                 .tilt(0)
                                                                 .build()));
        }
        else
        {
            if (stepSpin <= stepSpinMax)
            {
                stepSpin++;
                map.animateCamera(CameraUpdateFactory.newCameraPosition(CameraPosition.builder()
                                                                        .target(latLng)
                                                                        .zoom(initZoom + stepZoomDetent * stepZoom)
                                                                        .bearing(stepSpinDetent * (stepSpin - 1))
                                                                        .tilt(60)
                                                                        .build()), mapHopDelay, cameraAnimation);
            }
            else
            {
                stepZoom++;
                map.animateCamera(CameraUpdateFactory.newCameraPosition(CameraPosition.builder()
                                                                        .target(latLng)
                                                                        .zoom(initZoom + stepZoomDetent * stepZoom)
                                                                        .bearing(0)
                                                                        .tilt(0)
                                                                        .build()), mapHopDelay, cameraAnimation);
            }
        }
    }

    @Override
    public void onCancel()
    {}

};

1
嗨!听起来很有趣,我还没有使用过回调函数,我会试一试的。谢谢你发布代码! - rupps

1

好的,我希望有人能提供更好的答案,但是在我做过的许多实验中,使用animateCamera无法获得令人满意的平滑滚动。

即使只改变接近的点的Lat/Lng,摄像师仍然会进行惊人的起飞和降落。

我用以下程序有过有限的廉价动画成功:

    private void animateTo(double lat, double lon, double zoom, double bearing, double tilt, final int milliseconds) {

        if (mMapInstance==null) return;
        mMapInstance.setMapType(paramMapMode);
        mCurrentPosition=new LatLng(lat,lon);

        // animate camera jumps too much
        // so we set the camera instantly to the next point

        mMapInstance.moveCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition(mCurrentPosition,(float)zoom, (float)tilt, (float)bearing)));

        // give Android a break so it can load tiles. If I start the animation
        // without pause, no tile loading is done

        mMap.postDelayed(new Runnable(){
            @Override
            public void run() {
                // keeping numbers small you get a nice scrolling effect
                mMapInstance.animateCamera(CameraUpdateFactory.scrollBy(250-(float)Math.random()*500-250, 250-(float)Math.random()*500),milliseconds,null);

            }},500);

    }

这个程序在以10000毫秒为值调用时,会前往一个点,然后在随机方向上进行飞越动画,同时保持缩放平稳。由于像素值非常小,很可能已经缓存了所有内容。
有没有更好的解决方案?尝试注入触摸事件以模拟“触摸”抛掷是否合理或可行?

4
您不能在mMap上调用postDelayed() - IgorGanapolsky

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接