百度地图——显示小车轨迹动画回放

百度地图,Android显示车辆轨迹动画

 

初次设计想就用百度自带的显示覆盖物的方式,计算两个坐标点的距离,添加短距离的坐标点,然后在密密麻麻的坐标点之间显示,隐藏覆盖物,形成移动的视觉效果。
后来发现会创建较大的内存,而且效果不佳。
最后选择添加View的方法,利用addView方法添加小车的view,利用Android动画,同步和异步结合显示小车运行。
主要几个注意点和方案是:
  1. 计算小车转弯的角度,判断顺时逆时针。
  2. 计算地图缩放比例,依据是一组经纬度的最大距离值
  3. 在显示动画的时候地图是不能缩放的,因为经纬度和屏幕坐标转化不是实时的,数据是在调用接口时屏幕当前的比例尺转化。
  4. 还有就是当动画前屏幕被缩放了,轨迹已经超出了屏幕显示,就计算下一个车辆到达的点在不在屏幕上,不在的话就移动地图,将该点设置为中心点,这个并不完善

代码片段

地图移动到某一点,并且设置缩放比例。
    @Override
    public void MoveToPoint(List<LatLng> list) {
        /**
         * 设置地图移动到指定位置
         */
        // 定义地图状态
        //数字越小,比例尺越大
        Double lat=new Double(0),lng=new Double(0);
        double latlng[]=new double[2];
        int zooms=getZoomnum(latlng,list);
        Log.i(TAG, "lat lng:" + latlng[0] + "__  " + latlng[1]+"zoom   "+zooms);
        MapStatus mMapStatus = new MapStatus.Builder().target(new LatLng(latlng[0],latlng[1])).zoom(zooms)
                .build();
        // 定义MapStatusUpdate对象,以便描述地图状态将要发生的变化
        MapStatusUpdate mMapStatusUpdate = MapStatusUpdateFactory
                .newMapStatus(mMapStatus);
        // 改变地图状态
        mBaiduMap.setMapStatus(mMapStatusUpdate);
    }
//根据轨迹,一组坐标值计算缩放比例
    public int getZoomnum(double[] lalg,final List<LatLng> pointlist){
        int zoomSize[]={5,10,20,50,100,200,500,1000,2000,5000,10000,20000};//分别对应于zoom 21,20,19,18,17,16,15,14,13,12,11,10
        int i,j;
        double max=0,temp;
        for(i=0;i<pointlist.size();i++)
        {
            for(j=i+1;j<pointlist.size();j++)
            {
                temp=DistanceUtil.getDistance(pointlist.get(i),pointlist.get(j));
                if(temp>max){
                    max=temp;
                    lalg[0]=(pointlist.get(i).latitude+pointlist.get(j).latitude)/2;
                    lalg[1]=(pointlist.get(i).longitude+pointlist.get(j).longitude)/2;
                    Log.i(TAG,"lat lng:"+lalg[0]+"_dadsa_  "+lalg[1]);

                }
            }
        }
        Log.i(TAG,"max:  "+max);
        for(i=0;i<11;i++)
        {
            if(max>zoomSize[i]*12&&max<zoomSize[i+1]*12) {
                Log.i(TAG,"ixiabio: "+i);
                return 20 - i;
            }
        }
        if(max<zoomSize[0]*12)return 21;
        else return 10;
    }
利用向量知识计算方向角,顺时针旋转为正,逆时针为负。
  //计算两个向量的方向角,并根据顺时针返回正值,逆时针返回负值
    public float getangle(Point p1,Point p2,Point p3){
        double xp1p2=p2.x-p1.x;
        double yp1p2=p2.y-p1.y;
        double xp2p3=p3.x-p2.x;
        double yp2p3=p3.y-p2.y;
        double a1=Math.sqrt(xp1p2*xp1p2+yp1p2*yp1p2);
        double b1=Math.sqrt(xp2p3*xp2p3+yp2p3*yp2p3);
        double ab=xp1p2*xp2p3+yp1p2*yp2p3;
        float angle;
        if((a1*b1)!=0)
            angle =(float)Math.acos(ab/(a1*b1));
        else angle=0;
        double a_b=xp1p2*yp2p3-xp2p3*yp1p2;
        if(a_b<0)angle=-angle;
        return angle*180/(float)Math.PI;
    }

核心部分,动画绘制
//行车的时候,地图不能缩放,因为经纬度转化成坐标值是以当时地图的比例尺进行转化的
    public void rotateyAnimRun(final View view,final List<Point> list)
    {
        //ObjectAnimator的父类是valueAnimator,爷爷类是Animator.
        List<Animator> lt= new ArrayList<Animator>();
        Log.i(TAG,"lt size: "+lt.size());
        int size=list.size();
        float t1=0f;
        AnimatorSet set = new AnimatorSet();
        int i=0;
        carPathlist_point=list;
        for (i=0;i<size-1;i++){
            Animator animator,animator2;
            int k=i;//计数车子不动相同的经纬度情况
            while(i<size-1&&list.get(i).x==list.get(i+1).x&&list.get(i).y==list.get(i+1).y)i++;
            if(i==size-1)break;
            Log.i(TAG,"坐标: "+list.get(i).x+"____"+list.get(i).y);
            //PropertyValuesHolder属性holder,分别设置X,Y方向的移动值,然后调用ofPropertyValuesHolder设置属性值,这个是异步叠加动画。
            //参数指的是相对于view最初位置的偏移值
            PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("translationX", list.get(i).x-list.get(0).x,
                    list.get(i+1).x-list.get(0).x);
            PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("translationY", list.get(i).y-list.get(0).y,
                    list.get(i+1).y-list.get(0).y);
            PropertyValuesHolder pvhR;
            //监听在小车运行的时候如果下一个坐标点不在地图内,则将地图的中心点设置为下一个坐标点。
            class newAnListener implements Animator.AnimatorListener{
                private int center;
                public newAnListener(int center_){center=center_;}
                @Override
                public void onAnimationStart(Animator animation) {
                    WindowManager wm = (WindowManager) BaiduMapActivity.this
                            .getSystemService(Context.WINDOW_SERVICE);
                    int width = wm.getDefaultDisplay().getWidth();
                    int height = wm.getDefaultDisplay().getHeight();
                    Log.i(TAG, "width: " + width + "height: " + height + "mapCenter: " + center);
                    Log.i(TAG, "x: " + list.get(center + 1).x + "y: " + list.get(center + 1).y);
                    if (list.get(center + 1).x < 0 ||
                            list.get(center + 1).y < 0 ||
                            list.get(center + 1).x > width ||
                            list.get(center + 1).y > height) {
                        Log.i(TAG, "不是大了就是小了");
                        MapStatusUpdate mMapStatusUpdate = MapStatusUpdateFactory.newLatLng(carPathlist.get(center));
                        // 改变地图状态
                        mBaiduMap.setMapStatus(mMapStatusUpdate);
                    }
                }
                @Override
                public void onAnimationEnd(Animator animation) {}
                @Override
                public void onAnimationCancel(Animator animation) {}
                @Override
                public void onAnimationRepeat(Animator animation) {}
            };
            if(k==0) {
                float angle =getangle(new Point(list.get(i).x-1,list.get(i).y),list.get(i),list.get(i+1));
                Log.i(TAG, "angle:   "+angle);
                t1=t1+angle;
                pvhR = PropertyValuesHolder.ofFloat("rotation", t1);
                animator2=ObjectAnimator.ofPropertyValuesHolder(view, pvhR).setDuration(500);
                animator2.addListener(new newAnListener(i));
            }
            else{
                Log.i(TAG,"k:   "+k+"i:   "+i);
                float angle =getangle(list.get(k-1),list.get(i),list.get(i+1));
                Log.i(TAG, "angle:   "+angle);
                t1=t1+angle;
                pvhR = PropertyValuesHolder.ofFloat("rotation", t1);
                animator2=ObjectAnimator.ofPropertyValuesHolder(view, pvhR).setDuration(500);
                animator2.addListener(new newAnListener(i));
            }
            animator= ObjectAnimator.ofPropertyValuesHolder(view, pvhX, pvhY).setDuration(1000);
            //先旋转再直行
            lt.add(animator2);
            lt.add(animator);
        }
        //顺序执行Animator list中的动画效果
            set.playSequentially(lt);
        set.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
                //所有手势不可用
                mUiSettings.setAllGesturesEnabled(false);
                mMapView.showZoomControls(false);
                lay_showpath.setClickable(false);
                Log.i(TAG, "set_____________start");
            }
            @Override
            public void onAnimationEnd(Animator animation) {
                mMapView.removeViewInLayout(view);
                //所有手势可用
                mUiSettings.setAllGesturesEnabled(true);
                mMapView.showZoomControls(true);
                lay_showpath.setClickable(true);
                Log.i(TAG, "set_____________end");
            }
            @Override
            public void onAnimationCancel(Animator animation) {
            }
            @Override
            public void onAnimationRepeat(Animator animation) {
            }
        });
//可以将会设置绘制动画,设置在监听百度地图已经加载完毕的事件里
            set.start();
        Log.i(TAG, "lt end size: " + lt.size());
    }
添加该view到百度地图。
    @Override
    public void    DrawDynaPath(final List<LatLng> pointlist) {
        //获取小车的view
        Bitmap bitmap= BitmapFactory.decodeResource(getResources(), R.drawable.ic_vehicle_location_current);
        ImageView iv=new ImageView(this);
        iv.setImageBitmap(bitmap);
        Log.i(TAG, "size():" + pointlist.size());
        Projection pj=mBaiduMap.getProjection();
        //所有经纬度转化成坐标
        List<Point> list=new ArrayList<Point>();
        for(LatLng ll:pointlist){
          list.add(pj.toScreenLocation(ll));
        }
        mMapView.removeViewInLayout(iv);
        //	layoutMode(MapViewLayoutParams.ELayoutMode mode 指定 MapViewLayoutParams 的方式:屏幕坐标或者地图经纬度坐标
        //absoluteMode是不随地图变化而移动的,mapMode是随地图移动
        MapViewLayoutParams mlp = new MapViewLayoutParams.Builder().
                layoutMode(MapViewLayoutParams.ELayoutMode.mapMode).
                position(pointlist.get(0)).
                width(MapViewLayoutParams.WRAP_CONTENT).
                height(MapViewLayoutParams.WRAP_CONTENT).build();
        Log.i(TAG,"list.get(0):"+list.get(0).toString());
//        mMapView.removeAllViews();
        rotateyAnimRun(iv, list);
        mMapView.addView(iv, mlp);
//        layout_baidumap.removeAllViewsInLayout();
//        mMapView.addView(parent);
        mMapView.refreshDrawableState();
    }




 
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值