百度地图小车移动

基于百度地图,覆盖物(小车)平滑移动

先看一下效果


直接贴上源码

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;

import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.Marker;
import com.baidu.mapapi.map.MarkerOptions;
import com.baidu.mapapi.map.OverlayOptions;
import com.baidu.mapapi.model.LatLng;

/**
 * 平滑测试
 */
public class MapTest1 extends Activity {
    private MapView mMapView;
    private BaiduMap mBaiduMap;
    private Marker mMoveMarker;// 定义地图 Marker 覆盖物
    private Handler mHandler;

    // 通过设置间隔时间和距离可以控制速度和图标移动的距离
    private int TIME_INTERVAL = 80;// 时间间隔,线程休息的间隔
    private double DISTANCE = 0;// 距离
    private int time = 3000;// 每隔3秒钟,模拟掉一次获取位置的接口
    private int moveFinishInterval = 4000;// 4秒钟内,完成移动

    private int pointIndex = 0;// 取位置的下标
    LatLng startPoint;
    Handler pointHandler = new Handler();
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            // 模拟每次掉接口拿到的数据
            if (pointIndex >= latlngs.length - 1) {
                pointIndex = 0;
            }
            LatLng endPoint = latlngs[++pointIndex];

            carMove(startPoint, endPoint);

            startPoint = endPoint;
            pointHandler.postDelayed(this, time);
        }
    };

    /**
     * 这一段的总长度
     * 用两个点的经纬度和勾股定理,求得两个点之间的连线长度
     */
    private double getLength(LatLng fromPoint, LatLng toPoint) {
        if (toPoint.longitude == fromPoint.longitude) {
            return Double.MAX_VALUE;
        }
        return Math.sqrt(Math.pow(Math.abs(toPoint.latitude - fromPoint.latitude), 2) + Math.pow(Math.abs(toPoint.longitude - fromPoint.longitude), 2));
    }

    /**
     * 小车移动的逻辑
     */
    private void carMove(final LatLng startPoint, final LatLng endPoint) {
        new Thread() {
            @Override
            public void run() {
                super.run();
                mMoveMarker.setPosition(startPoint);// 设置 Marker 覆盖物的位置坐标
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        // 更新覆盖物的旋转角度
                        if (mMapView == null) {
                            return;
                        }
                        mMoveMarker.setRotate((float) getAngle(startPoint, endPoint));// 设置 Marker 覆盖物旋转角度,逆时针
                    }
                });

                boolean xIsReverse = endPoint.latitude > startPoint.latitude;// x方向,像右是正方向
                boolean yIsReverse = endPoint.longitude > startPoint.longitude;// y方向,像上是正方向
                double length = getLength(startPoint, endPoint);// 求得两个点之间的连线长度
                DISTANCE = length / (moveFinishInterval / TIME_INTERVAL);// 每4000/80毫秒移动的距离
                double xMove = xMoveDistance(startPoint, endPoint, DISTANCE, length);// 计算每次x方向上移动的距离
                double yMove = yMoveDistance(startPoint, endPoint, DISTANCE, length);// 计算每次y方向上移动的距离
                for (int i = 0; i < moveFinishInterval / TIME_INTERVAL; i++) {// 遍历4000/80次
                    double x, y;

                    if (xIsReverse) {// 向右移动
                        x = startPoint.latitude + i * xMove;
                    } else {// 向左移动
                        x = startPoint.latitude - i * xMove;
                    }

                    if (yIsReverse) {// 向上
                        y = startPoint.longitude + i * yMove;
                    } else {// 向下
                        y = startPoint.longitude - i * yMove;
                    }
                    LatLng latLng = new LatLng(x, y);

                    final LatLng finalLatLng = latLng;
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            if (mMapView == null) {
                                return;
                            }
                            // 刷新覆盖物的位置
                            mMoveMarker.setPosition(finalLatLng);
                        }
                    });
                    try {
                        Thread.sleep(moveFinishInterval / TIME_INTERVAL);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }

    /**
     * X方向移动的距离
     */
    private double xMoveDistance(LatLng startPoint, LatLng endPoint, double DISTANCE, double length) {
        return Math.abs((endPoint.latitude - startPoint.latitude) / length * DISTANCE);
    }

    /**
     * Y方向移动的距离
     */
    private double yMoveDistance(LatLng startPoint, LatLng endPoint, double DISTANCE, double length) {
        return Math.abs((endPoint.longitude - startPoint.longitude) / length * DISTANCE);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_map_test);
        mMapView = (MapView) findViewById(R.id.bmapView);

        mMapView.onCreate(this, savedInstanceState);
        mBaiduMap = mMapView.getMap();
        mHandler = new Handler(Looper.getMainLooper());

        intiMarker();

        startPoint = latlngs[pointIndex];
        pointHandler.postDelayed(runnable, time);// 每3秒执行一次runnable.
    }

    /**
     * 初始化覆盖物
     */
    private void intiMarker() {
        OverlayOptions markerOptions = new MarkerOptions().flat(true).anchor(0.5f, 0.5f).icon(BitmapDescriptorFactory
                .fromResource(R.drawable.icon_bus_logo)).position(latlngs[0]).rotate((float) getAngle(latlngs[0], latlngs[1]));
        // 添加覆盖物小车的图标
        mMoveMarker = (Marker) mBaiduMap.addOverlay(markerOptions);

        // 移动位置
        MapStatusUpdate mapStatusUpdate = MapStatusUpdateFactory.newLatLng(latlngs[0]);
        if (mBaiduMap != null && mapStatusUpdate != null) {
            mBaiduMap.animateMapStatus(mapStatusUpdate);
        }
    }

    /**
     * 根据两点算取图标转的角度
     */
    private double getAngle(LatLng fromPoint, LatLng toPoint) {
        double slope = getSlope(fromPoint, toPoint);
        if (slope == Double.MAX_VALUE) {
            if (toPoint.latitude > fromPoint.latitude) {
                return 0;
            } else {
                return 180;
            }
        }
        float deltAngle = 0;
        if ((toPoint.latitude - fromPoint.latitude) * slope < 0) {
            deltAngle = 180;
        }
        double radio = Math.atan(slope);
        double angle = 180 * (radio / Math.PI) + deltAngle - 90;
        return angle;
    }

    /**
     * 算斜率
     * 结束的维度减去开始的维度(横) / 结束的经度减去开始的经度(竖)
     * x / y
     */
    private double getSlope(LatLng fromPoint, LatLng toPoint) {
        if (toPoint.longitude == fromPoint.longitude) {
            return Double.MAX_VALUE;
        }
        double slope = ((toPoint.latitude - fromPoint.latitude) / (toPoint.longitude - fromPoint.longitude));
        return slope;
    }

    /**
     * 方法必须重写
     */
    @Override
    protected void onResume() {
        super.onResume();
        mMapView.onResume();
    }

    /**
     * 方法必须重写
     */
    @Override
    protected void onPause() {
        super.onPause();
        mMapView.onPause();
    }

    /**
     * 方法必须重写
     */
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        pointHandler.removeCallbacks(runnable);
        mMapView.onSaveInstanceState(outState);
    }

    /**
     * 方法必须重写
     */
    @Override
    protected void onDestroy() {
        super.onDestroy();
        mMapView.onDestroy();
        mBaiduMap.clear();
    }

    private static final LatLng[] latlngs = new LatLng[]{
            new LatLng(40.055826, 116.307917),
            new LatLng(40.055916, 116.308455),
            new LatLng(40.055967, 116.308549),
            new LatLng(40.056014, 116.308574),
            new LatLng(40.056440, 116.308485),
            new LatLng(40.056816, 116.308352),
            new LatLng(40.057997, 116.307725),
            new LatLng(40.058022, 116.307693),
            new LatLng(40.058029, 116.307590),
            new LatLng(40.057913, 116.307119),
            new LatLng(40.057850, 116.306945),
            new LatLng(40.057756, 116.306915),
            new LatLng(40.057225, 116.307164),
            new LatLng(40.056134, 116.307546),
            new LatLng(40.055879, 116.307636),
            new LatLng(40.055826, 116.307697),
    };
}

大多地方都添加了注释,具体思路就是,每次获取车的位置时,根据这次的位置和上个获取的位置来做移动逻辑(所以和车辆实际的位置会有延迟)。我模拟的数据是每隔3秒调用一次接口,然后4秒钟完成小车移动的逻辑。因为是在循环里不停的设置小车的位置,所以感觉整个小车移动感觉不太平滑,不知道怎么用动画来设置,如果有人做过,可以告诉我。
以上
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值