高德地图轨迹回放,消息框内展示车辆速度且随车辆移动-升级支持调整速度、回放进度

使用高德地图回放车辆GPS轨迹,并添加速度和回放进度条,并支持调整,效果如下:

示例.gif

新增的功能:

基础版本,有如下升级

  1. 速度条:可以拖动以调整车辆回放速度,且从当前位置继续回放
  2. 进度条:进度条表示车辆已回放的百分比,且拖动进度条车辆定位到相应的位置并继续回放

###思路分析

  • 高德和marker回放相关的API
//主要靠他回放
moveAlong(path:Array,speed:Number,f:Function,circlable:Boolean)
//点移动到另一个位置,移动进度条车辆跟随移动
moveTo(lnglat:[LngLat],speed:Number, f:Function)
//停止播放
stopMove()
//继续播放 未用到
resumeMove()

未发现可以从指定点开始播放的API,所以只能迂回下了

  • 假设我们得知从第100个点,开始回放;可以停止当前回放,并且从截取100到最后 的轨迹点,生成一个临时轨迹,让marker来moveAlong
  • 所以在我们拖动速度条后,需要知道当前回放到哪个点
  • 所以在我们拖动进度条后,需要知道当前回放到哪个点
  • 进度条随车辆回放变化,需要知道当期回放到哪个点,再除以轨迹点总个数以设置回放百分比

所以关键是获取当前回放到哪个点,如下即可解决该问题

AMap.event.addListener(carMarker, 'moving', function (e) {
        console.log("当前已回放: "+ e.passedPath.length)
    });

关于进度条本文用的是 ion.rangeSlider,示例和用法大家可以参考官网,很简单
主要用到如下事件,我写了中文备注,大家也可以参考官网的示例




    $("#demo_0").ionRangeSlider({
        skin: "big",
        min: 0,
        max: 10,
        from: 5,
        onStart: function (data) {
            // fired then range slider is ready
        },
        onChange: function (data) {
            // fired on every range slider update-用鼠标拖动进度条时触发
        },
        onFinish: function (data) {
            // fired on pointer release-用鼠标拖动进度条后,释放鼠标触发
        },
        onUpdate: function (data) {
            // fired on changing slider with Update method-用JS方法更新进度条值后触发
        }
    });

那么实现思路就很清晰了

  • 车辆移动,进度条跟随变化:当前车辆已回放点的个数➗轨迹点总个数 (代码137行)
  • 修改速度,车辆从当前位置按新速度回放: 当前车辆停止回放,从当期位置到最后重新生成一段线路,车辆根据新轨迹回放
  • 修改进度,车辆定位到相应位置:根据进度条的百分比✖️轨迹总个数,即可定位到当前百分比对应的轨迹点,将车辆移动到该位置即可(onUpdate事件)
  • 修改进度后,车辆从当前位置回放:根据进度条的百分比✖️轨迹总个数,得到当前位置,生成从当前位置到最后的路径,并回放即可(onFinish事件)

源码如下

<html>
<head>
    <!--bootstrap css-->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    <!--rangeSlider css 进度条-->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.3.0/css/ion.rangeSlider.min.css"/>

    <!--jquery js-->
    <script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script>
    <!--bootstrap js-->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
    <!--Amap js 高德-->
    <script src="https://webapi.amap.com/maps?v=1.3&key=fadee97bdcbf2dde564994f5deef0b58&plugin=AMap.Autocomplete,AMap.Walking,AMap.PlaceSearch,AMap.PolyEditor,AMap.CircleEditor,AMap.Transfer,AMap.Driving,AMap.CitySearch,AMap.Heatmap,AMap.Size" type="text/javascript"></script>
    <script src="https://webapi.amap.com/ui/1.0/main.js?v=1.0.11"></script>
    <!--rangeSlider js 进度条-->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.3.0/js/ion.rangeSlider.min.js"></script>

</head>

<body class="container">

<div class="row">
    <div class="col-md-12">
        <!--速度条-->
        <div id="ionrange_speed"></div>
    </div>
    <div class="col-md-12">
        <!--进度条-->
        <div id="ionrange_process"></div>
    </div>
    <div class="col-md-12">
        <button type="button" class="btn btn-info pull-right" onclick="carMarker.stopMove()">暂停</button>
        <button type="button" class="btn btn-info pull-right" onclick="playCar()">播放</button>
    </div>
</div>

<div class="row">
    <div class="col-md-12">
        <!--地图-->
        <div id="mapContainer" style="height: 100%;width: 100%;">
        </div>
    </div>
</div>

</body>


<script type="text/javascript">
    var carSpeed = 5000;//移动速度,后面调整速度已这个为基准
    var carMarker; //回放车辆
    var VEHICLE_PLAY_PROCESS = 0; //车辆当前回放到的百分比进度
    var VEHICLE_PATH_REPLAY_START = 0;//当前回放的起点索引, 改变速度和改变进度条的时候,根据进度条百分比重新计算该数值,并从该位置开始再次回放

    // 车辆轨迹、速度数据
    var routeInfo = [{"lng":123.390381,"lat":41.929537,"speed":0},{"lng":123.390315,"lat":41.929736,"speed":13},{"lng":123.390331,"lat":41.930286,"speed":19},{"lng":123.390365,"lat":41.930819,"speed":25},{"lng":123.390381,"lat":41.931436,"speed":25},{"lng":123.390398,"lat":41.932069,"speed":24},{"lng":123.390416,"lat":41.932686,"speed":24},{"lng":123.390482,"lat":41.933203,"speed":20},{"lng":123.390582,"lat":41.933269,"speed":19},{"lng":123.390716,"lat":41.933287,"speed":19},{"lng":123.391433,"lat":41.933337,"speed":24},{"lng":123.392268,"lat":41.933305,"speed":26},{"lng":123.392402,"lat":41.933238,"speed":26},{"lng":123.392652,"lat":41.933071,"speed":24},{"lng":123.392819,"lat":41.932788,"speed":26},{"lng":123.393085,"lat":41.932205,"speed":30},{"lng":123.393536,"lat":41.931422,"speed":35},{"lng":123.393803,"lat":41.930956,"speed":39},{"lng":123.39407,"lat":41.930472,"speed":39},{"lng":123.394287,"lat":41.930006,"speed":41},{"lng":123.394504,"lat":41.929506,"speed":43},{"lng":123.394704,"lat":41.928972,"speed":44},{"lng":123.394921,"lat":41.928423,"speed":46},{"lng":123.395137,"lat":41.927857,"speed":46},{"lng":123.395354,"lat":41.92729,"speed":48},{"lng":123.395588,"lat":41.926707,"speed":46},{"lng":123.395822,"lat":41.926123,"speed":49},{"lng":123.396055,"lat":41.92554,"speed":47},{"lng":123.396338,"lat":41.924991,"speed":44},{"lng":123.396639,"lat":41.924508,"speed":41},{"lng":123.396939,"lat":41.924091,"speed":35},{"lng":123.397506,"lat":41.923391,"speed":28},{"lng":123.397974,"lat":41.922825,"speed":22},{"lng":123.398407,"lat":41.922375,"speed":13},{"lng":123.398841,"lat":41.921942,"speed":15},{"lng":123.399241,"lat":41.921525,"speed":24},{"lng":123.399791,"lat":41.920975,"speed":31},{"lng":123.400159,"lat":41.92061,"speed":35},{"lng":123.400876,"lat":41.919876,"speed":37},{"lng":123.401277,"lat":41.91946,"speed":41},{"lng":123.401693,"lat":41.919026,"speed":41},{"lng":123.40211,"lat":41.918576,"speed":43},{"lng":123.402527,"lat":41.918127,"spe
### 实现路径回放功能 在 Android 应用中使用高德地图 SDK 实现路径回放功能涉及多个组件的协同工作。具体来说,通过 `Marker` 对象表示移动的目标位置,并利用定时器或其他机制更新这些目标的位置以模拟运动效果。 为了实现这一功能,可以按照如下方式构建应用程序逻辑: #### 初始化地图并加载初始数据 首先,在 Activity 或 Fragment 的生命周期方法内初始化 AMap 对象,并设置必要的监听器以便处理交互事件[^1]。 ```java AMap aMap; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_map); mapFragment = (SupportMapFragment)getSupportFragmentManager() .findFragmentById(R.id.map); mapFragment.getMapAsync(this); // 异步获取地图实例 } @Override public void onMapReady(AMap amap){ this.aMap = amap; } ``` #### 添加标记与绘制轨迹线 当准备就绪后,可以根据预先存储好的坐标列表创建 `PolylineOptions` 来描绘整个行程路线;同时为每一个关键节点添加对应的 `Marker` 标记[^4]。 ```java List<LatLng> lineArr = new ArrayList<>(); // 假设这里已经填充好了lineArr的数据... aMap.addPolyline(new PolylineOptions().addAll(lineArr).width(10).color(Color.argb(255, 1, 178, 239))); for(LatLng point : lineArr){ Marker marker = aMap.addMarker(new MarkerOptions().position(point)); } ``` #### 控制播放进度条 为了让用户体验更加友好,通常会加入一个 `SeekBar` 组件让用户能够手动控制回放速度或暂停/继续操作。此时需要注册 `OnSeekBarChangeListener` 接口来响应用户的输入变化。 ```xml <!-- layout/activity_main.xml --> <SeekBar android:id="@+id/playback_seekbar" ... /> ``` ```java SeekBar seekBarPlaybackSpeed = findViewById(R.id.playback_seekbar); seekBarPlaybackSpeed.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onStartTrackingTouch(SeekBar arg0) {} @Override public void onStopTrackingTouch(SeekBar arg0) {} @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if(fromUser && isPlaying){ // 如果正在播放则调整速度 updatePlaybackRate(progress / 10f); } } }); ``` #### 处理后台消息提示 考虑到实际应用场景可能会遇到网络延迟等问题影响体验感,因此可以在适当时候调用类似 `showPopMsgInHandleThread()` 方法显示短暂的消息框告知当前状态给用户[^3]。 ```java if (!isStopped()) { DialogUtils.showPopMsgInHandleThread(MapActivity.this, mHandler, "请先停止轨迹回放路线!"); } else { startReplay(); } ``` 以上即是在 Android 平台上基于高德地图 API 构建路径回放特性的基本流程概述。当然这只是一个简化版的例子,真实项目里还需要考虑更多细节优化以及异常情况下的恢复策略等。
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值