• web技术分享| 【高德地图】实现自定义的轨迹回放


    在这里插入图片描述

    实现(轨迹回放)方式有两种:

    • 第一种是使用 JS APIAMap.PolyLine(折线)等图形配合实现。
    • 第二种是使用 JS APIAMapUI 组件库 配合使用,利用 PathSimplifier轨迹展示组件)绘制出行动轨迹。

    方案选择

    以上两种实现方式我们可以根据两个因素 来决定哪一种更加适合自己:节点数量 的多少、排布的密集度

    前者适合节点数量较少,排布比较稀松,例如,出租车轨迹回放,出租车行驶速度快,周期上报的时间也会相对较长。后者更加针对节点数量巨大、排布密集的路径,按秒记录位置的飞机行进轨迹,精细的地理边界等等。

    实现流程

    无论选择两种方式,我们都需要先收集到客户端上报的信息,这些信息可以自定义,通常我们会包含:经纬度、速度、逆编码之后的地理位置、方向、海拔 等基本地理信息,同时我们也可以加入一些自定义 的信息,例如:人员信息(头像昵称等)、出行信息(订单等)。

    实现的流程:

    • 客户端按(时间)周期上报地理信息以及自定义信息。
    • 服务端按时间轴存储客户上报的信息。
    • 按(时间等)条件查询出用户的轨迹,并通过简化算法去除一部分节点(例如,节点距离十分微小、或者多个点都在同一条直线、3点之间,其中一点略有偏差无法绘制成直线等等),最终获得适合绘制的路径(数组)。
    • 根据路径去绘制用户的行动轨迹。

    路径简化算法(可选)

    客户端上报的数据是按时间周期上报的,也就是说每个时间都对应了一个经纬度,经纬度在地图上就是一个又一个点,将这些点连接时,我们会得到 N 多条折线,为了绘制的轨迹更加美观,行动路线更加明确平滑,通常我们需要一个算法来简化折线。

    例如:

    • A 点和 B 点,两者距离不到 1 像素,则可以去掉 B 点,只留 A 点。
    • ABC 三点在一条直线上,或者,B 点仅仅稍微偏离 A 点和 C 点构成的线段,那么 B 点就可以去掉。

    这里官方也推荐了一种算法库 simplify.js供大家参考,这里不做过多的阐述。

    实现示例

    车辆轨迹回放

    这里我们使用第一种方式来实现 - 利用 JS APIAMap.PolyLine

    在这里插入图片描述

    实现原理:

    • 在地图上绘制车辆标记AMap.Marker)。
    • 利用 AMap.PolyLine 绘制出两条轨迹:历史轨迹驾驶途径过的轨迹,以颜色区分。
    • 按照一定的速度使车辆前进,并监听 Maker 移动的事件,在事件回调中,将车辆(Marker)位置设置为地图中心点,给使用者视觉主观上一种车辆在前进的感觉,同时延长驾驶途径过的轨迹
    • 对于实现场景比较复杂的,需要进行自定义处理的比如:
      • 查看每个节点的数据,我们可以把每个节点给绘制出来,节点被点击时显示该节点的数据。
      • 移动倍速播放,首先按上报的时间间隔来播放,选择倍速之后,改变 MarKer 移动的 duration
      • 其他自定义。

    自定义 API

    我们可以让车辆:

    • 开始移动
    • 暂停移动
    • 恢复移动
    • 停止移动

    代码示例

    AMap.plugin('AMap.MoveAnimation', function(){
      var marker, lineArr = [[116.478935,39.997761],[116.478939,39.997825],[116.478912,39.998549],[116.478912,39.998549],[116.478998,39.998555],[116.478998,39.998555],[116.479282,39.99856],[116.479658,39.998528],[116.480151,39.998453],[116.480784,39.998302],[116.480784,39.998302],[116.481149,39.998184],[116.481573,39.997997],[116.481863,39.997846],[116.482072,39.997718],[116.482362,39.997718],[116.483633,39.998935],[116.48367,39.998968],[116.484648,39.999861]];
    
      var map = new AMap.Map("container", {
        resizeEnable: true,
        center: [116.397428, 39.90923],
        zoom: 17
      });
    
      marker = new AMap.Marker({
        map: map,
        position: [116.478935,39.997761],
        icon: "https://a.amap.com/jsapi_demos/static/demo-center-v2/car.png",
        offset: new AMap.Pixel(-13, -26),
      });
    
      // 绘制历史轨迹
      var polyline = new AMap.Polyline({
        map: map,
        path: lineArr,
        showDir:true,
        strokeColor: "#28F",  //线颜色
        // strokeOpacity: 1,     //线透明度
        strokeWeight: 6,      //线宽
        // strokeStyle: "solid"  //线样式
      });  
    	// 驾驶途径过的轨迹
      var passedPolyline = new AMap.Polyline({
        map: map,
        strokeColor: "#AF5",  //线颜色
        strokeWeight: 6,      //线宽
      });
    
    	// 监听车辆移动事件
      marker.on('moving', function (e) {
    	  // 延长驾驶途径过的轨迹
        passedPolyline.setPath(e.passedPath);
        // 将车辆位置设置为地图中心点
        map.setCenter(e.target.getPosition(),true)
      });
    
      map.setFitView();
    	
    	// 开始移动
      window.startAnimation = function startAnimation () {
        marker.moveAlong(lineArr, {
          // 每一段的时长
          duration: 500,//可根据实际采集时间间隔设置
          // JSAPI2.0 是否延道路自动设置角度在 moveAlong 里设置
          autoRotation: true,
        });
      };
      // 暂停移动
      window.pauseAnimation = function () {
      	marker.pauseMove();
      };
    	// 恢复移动
      window.resumeAnimation = function () {
      	marker.resumeMove();
      };
    	// 停止移动
      window.stopAnimation = function () {
      	marker.stopMove();
      };
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65

    参考链接:https://lbs.amap.com/demo/jsapi-v2/example/marker/replaying-historical-running-data

    飞机航班的轨迹回放

    使用 JS APIAMapUI 组件库 配合使用,利用 PathSimplifier轨迹展示组件)绘制出行动轨迹,这种方案比较简单,只需要进行一些配置即可,例如说方案一中的倍速播放就需要计算,同时还存在不能动态改变倍速的弊端,但是方案二却不会存在。

    实现原理:

    • 在地图上绘制飞机标记AMap.Marker)。
    • 利用 AMap.PolyLine 绘制出两条轨迹:历史轨迹驾驶途径过的轨迹,以颜色区分。
    • 配置轨迹的颜色,动画的速度等等。
    • 对于实现场景比较复杂的,需要进行自定义处理的,可以在PathSimplifier 提供的回调中进行配置及处理。

    示例代码

    //加载PathSimplifier,loadUI的路径参数为模块名中 'ui/' 之后的部分 
    AMapUI.load(['ui/misc/PathSimplifier'], function(PathSimplifier) {
    
        if (!PathSimplifier.supportCanvas) {
            alert('当前环境不支持 Canvas!');
            return;
        }
    
        //启动页面
        initPage(PathSimplifier);
    });
    
    function initPage(PathSimplifier) {
        //创建组件实例
        var pathSimplifierIns = new PathSimplifier({
            zIndex: 100,
            map: map, //所属的地图实例
            getPath: function(pathData, pathIndex) {
                //返回轨迹数据中的节点坐标信息,[AMap.LngLat, AMap.LngLat...] 或者 [[lng|number,lat|number],...]
                return pathData.path;
            },
            getHoverTitle: function(pathData, pathIndex, pointIndex) {
                //返回鼠标悬停时显示的信息
                if (pointIndex >= 0) {
                    //鼠标悬停在某个轨迹节点上
                    return pathData.name + ',点:' + pointIndex + '/' + pathData.path.length;
                }
                //鼠标悬停在节点之间的连线上
                return pathData.name + ',点数量' + pathData.path.length;
            },
            renderOptions: {
                //轨迹线的样式
                pathLineStyle: {
                    strokeStyle: 'red',
                    lineWidth: 6,
                    dirArrowStyle: true
                }
            }
        });
    
        //这里构建两条简单的轨迹,仅作示例
        pathSimplifierIns.setData([{
            name: '轨迹0',
            path: [
                [100.340417, 27.376994],
                [108.426354, 37.827452],
                [113.392174, 31.208439],
                [124.905846, 42.232876]
            ]
        }, {
            name: '大地线',
            //创建一条包括500个插值点的大地线
            path: PathSimplifier.getGeodesicPath([116.405289, 39.904987], [87.61792, 43.793308], 500)
        }]);
    
        //创建一个巡航器
        var navg0 = pathSimplifierIns.createPathNavigator(0, //关联第1条轨迹
            {
                loop: true, //循环播放
                speed: 1000000
            });
    
        navg0.start();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64

    参考链接:https://lbs.amap.com/demo/amap-ui/demos/amap-ui-pathsimplifier/index

    在这里插入图片描述

  • 相关阅读:
    Anaconda安装教程(Windows环境下)
    设计原则——合成复用原则
    【python初级】windows系统安装Anaconda3
    大数据毕业设计选题推荐-超级英雄运营数据监控平台-Hadoop-Spark-Hive
    京东店铺所有商品数据接口(JD.item_search_shop)
    JVM简介
    CF803F
    特征工程特征预处理归一化与标准化、鸢尾花种类预测代码实现
    vscode 配置c/c++环境,无法生成 *.exe文件
    探索自动化测试工具:Selenium的威力与应用
  • 原文地址:https://blog.csdn.net/anyRTC/article/details/125406086