轨迹回放组件实现方案

1,841 阅读4分钟

这是我参与8月更文挑战的第10天,活动详情查看:8月更文挑战

背景:

最近开发的大屏项目需要做一个轨迹播放功能。

因此想共享一下我写的轨迹组件代码,此处主要是设计思路,以及它如何在项目中使用(主要是参考下在设计时的配置项)。

下文中所有提到的hmap大家可以理解为arcgis的前端api或leaflet,hmap是公司内部的地图渲染引擎。本文只分享设计思路及涉及的配置项给大家提供组件设计参考及未来自己回忆。

项目展示效果如下:

实现思路

按照功能拆分分三步介绍如何实现图片中展示的效果。

一、添加轨迹点

1、 一般情况下,大屏项目中点位都会设计的比较酷炫还会有一些动效,所以我们把页面渲染交给vue组件,在js中使用Vue.extend + vm.$mount组合动态渲染点位。代码如下:

vue轨迹页面代码:

    //添加轨迹点
	addOrbitPoint(feature) {
	  //轨迹点序号数组(一个点可能经过多次)
      let numbers = feature._attributes.list.map(item => {
        return {
          num: item.num
        }
      })
      let orbitPoint = Vue.extend(OrbitPoint)
      let infoContent = new orbitPoint({
        propsData: {
          numbers: numbers,    //点位序号
          img: feature._attributes.orbitNormalImg ? feature._attributes.orbitNormalImg : '',//点位图标
          isAlarm: false //点位报警状态
        }
      })
	  //实例转为element对象
      let ele = infoContent.$mount().$el
      let param = {
        feature: feature,//hmap.Vector.Feature
        ele: ele,//dom对象
        name: 'orbitPoint',//图层名称
        times: true  //是否展示多次 用在点位时一般是可以多个,用在弹框一般是只有一个
      }
	  //调用地图公共方法展示复杂点位
      MapUtil.addInfoTemplate(param)
    },

MapUtil.js 组件代码

  //公共方法添加复杂点位和弹框
  addInfoTemplate(param) {
    param = Object.assign(
      {
        feature: null,//hmap.Vector.Feature
        ele: null,//dom对象
        name: null,//图层名称
        times: false, //在此图层下是否可以有多个同时存在
        offsetX: 0,
        offsetY: 0
      },
      param
    )
    let overlay = map.getLayersByName(param.name)[0] //查看图层是否已存在
    if (!overlay) {
      overlay = new hmap.layer.OverlayLayer(param.name)
      map.addLayer(overlay)
    }
    if (!param.feature._attributes.longitude) {
      return
    }
	//构建坐标点
    const coord1 = new hmap.basetype.Coordinate(
      Number(param.feature._attributes.longitude),
      Number(param.feature._attributes.latitude),
      0
    )
	//构建复杂点或弹框
    let simplePopup = new hmap.overlay.SimplePopup({
      domId: param.name + param.feature._attributes.placeCode,
      location: coord1,
      element: param.ele,
      offset: new hmap.basetype.Offset(param.offsetX, param.offsetY, 0)
    })
    //是否只存在一个
    if (!param.times) {
      overlay.removeAllOverlays() //清除所有
    }
    overlay.addOverlay(simplePopup)
  },

2、轨迹线路就是一条渐变的线hmap中有很多demo,可自行查阅。

轨迹组件部分代码:

      // 缩放到相应位置 hmap2.1.3点坐标重复时获取缓冲区会有问题
      // var polygon = lineString.getBuffer(0.1)
      // var extent = polygon.getExtent()
      if (!noRepeatPointList) {
        noRepeatPointList = data
      }
      let noRepeatPoint = []
      //无重复坐标点的数组
      for (var j = 0; j < noRepeatPointList.length; j++) {
        let noRepeatcoord = new hmap.basetype.Coordinate(
          Number(noRepeatPointList[j].longitude),
          Number(noRepeatPointList[j].latitude),
          0
        )
        let noRepeatPt = new hmap.geom.Point(noRepeatcoord)
        noRepeatPoint.push(noRepeatPt)
      }
      let noRepeatLine = new hmap.geom.Line(noRepeatPoint)
      var polygon = noRepeatLine.getBuffer(0.01)
      var extent = polygon.getExtent()
      map.zoomToExt(extent)

二、组件开发之如何实现播放功能 确定播放点的坐标

播放点坐标计算方法:

1、计算轨迹线的总长度。利用point.distanceTo(point)方法计算相邻两点间的距离并相加。

2、确定播放的时间如1000秒

根据总路程和时间可以得到速度也就是每一次播放的距离,加速或减速播放时直接倍速值乘每次播放的距离。

3、确定播放点的角度

根据两个坐标点的经纬度差值利用直角三角形函数计算出角度值

4、 确定坐标

根据第二步得到每次移动的距离和第三步得到的角度值,利用直角三角形函数算出在x方向上移动的距离和y轴方向上移动的距离

三、如何使用轨迹组件

1、引入组件BayonetTrace.js,同hmap引入方式相同。

	<script src="static/hmap.debug.js"></script>
	<script src="static/BayonetTrace.js"></script>

2、构建轨迹对象 传入hmap.Map,hmap.layer.VectorLayer,function(处理播放经过点位时展示弹框)

	var trace = new hmap.Biz.BayonetTrace(map, layer, callback)
	//设置轨迹默认播放速度因大屏展示需要设为8
	trace.speed(8)

3、设置轨迹线样式和走过的路径样式 样式属性参考hmap官方文档 hmap.style.LineSymbol

	var _style = {
	"Line" : {
	width: 3,
	color: [0, new hmap.style.Color(255, 216, 0, 0.6), 1.0, new hmap.style.Color(253, 126, 49, 0.6)]
	},
	"CompleteLine" : {
	width: 3,
	color: [0, new hmap.style.Color(255, 216, 0, 1), 1.0, new hmap.style.Color(253, 126, 49, 1)]
	}
	}
	trace._style=_style

4、设置起点样式和终点样式 样式属性参考hmap官方文档 hmap.style.Circle

	var startStyle={
	radius: 1,
	fillColor: new hmap.style.Color(255, 216, 0, 0.6),
	}
	trace.setStartStyle(startStyle) //设置移动物体初始样式
	trace.setendStyle(endStyle) //设置移动物体结束回放后的样式

5、设置起点样式和终点样式 样式属性参考hmap官方文档 hmap.style.Icon

	var moveStyle={
	opacity: 1,
	imgSrc: '/ctm01multdeploy/static/trace/images/orbitCircle.png',
	size: new hmap.basetype.Size(24, 24),
	anchor: [0.5, 0.5],
	offset: new hmap.basetype.Offset(0, 0, 0)
	}
	trace.setmoveStyle(moveStyle) //先设置样式在设置路径

6、添加轨迹 传入点位数组和无重复坐标点数组(原因在文中流程一第二点已说明)

	var data = [{
	"id": "K1",
	"latitude": "30.222066",
	"longitude": "120.20474"
	}, {
	"id": "K2",
	"latitude": "30.258439",
	"longitude": "120.206797"
	}];
	//处理数据获得无重复坐标点数组
	let noRepeatPointList = this.handleRepeatPoint(data)
	trace.setPath(data, noRepeatPointList) //设置路径
	trace.stopTime(1) //经过点位时展示弹框设置停留时间 单位 秒
	trace.setPathShow(true) //设置是否显示已经走过的路径

7、设置轨迹功能,开始播放、暂停、加速、减速等

	/**
	* 启动
	*/
	trace.start();
	/**
	* 轨迹移动暂停
	*/
	trace.pause();
	/**
	* 轨迹移动继续
	*/
	trace.resume();
	/**
	* 轨迹移动停止
	*/
	trace.stop();
	/**
	* 加速或减速
	*/
	trace.speed(s);
	/**
	* 轨迹移动重新开始
	*/
	trace.restart();
	/**
	* 定点重新播放
	*/
	trace.restart(startIndex,endIndex);

组件使用demo示例

前面分享了在项目中轨迹开发的思路,分享一个简单纯轨迹功能demo可更加直观的了解轨迹播放在设计时应该具备哪些功能。

运行结果如下:

总结

主要分享一下轨迹组件开发的思路,明确地图引擎在轨迹中做什么功能(画点画线),所以无论换成什么地图引擎比如arcgis或leaflet,我们只需要修改组件中画点和画线的方式。设计思路及原理都是可以照搬的。