--- title: Openlayers轨迹播放 date: 2020-12-25 author: ac tags: - 轨迹 categories: - GIS --- ## 轨迹播放 ![tracking](../images/openlayers/tracking.gif) 轨迹播放是非常常见的需求,像旅游路线、徒步轨迹或项目中的巡检人员的巡检轨迹的复盘等,可以回顾户外运动的轨迹,分析和规划最优的行进路线。 **实现思路** 轨迹通常是收集移动端发送回来的点集,将点集组织成线,渲染到地图上; - 获取轨迹数据,可以是线也可以是点集,将其渲染到地图上; - 创建移动点图层,将轨迹中的第一个点作为点要素的`geometry` - 通过设置步长对点集进行插值,得到轨迹播放的轨迹点集合; - 设置总时间,使用定时器`setTimeout`,在每个点的平均时间内,不断地改变移动点的`geometry`对象(将轨迹点集合中的点,设置到要素中) 我们先在[http://geojson.io/](http://geojson.io/)上绘制要使用的轨迹点,这里我们使用的是线要素`LineString`。 ![image-20201224114043053](../images/openlayers/image-20201224114043053.png) 初始化地图,将轨迹数据展示在地图上。如果是点集也可以在获取到数据后组织成线要素进行展示。 ```javascript var map = new ol.Map({ target: "map", layers:[ new ol.layer.Tile({ source: new ol.source.OSM() }) ], view: new ol.View({ // center: ol.proj.fromLonLat([113,23]), center: [113.9537, 22.5024], zoom: 14, projection:"EPSG:4326" }) }); //获取轨迹数据并展示在地图上 var trackSource = new ol.source.Vector(); var geojsonFormat = new ol.format.GeoJSON(); fetch("data/geojson/trackData.json").then(function(response){ return response.json(); }).then(function(result){ var features = geojsonFormat.readFeatures(result); trackSource.addFeatures(features); //showCarLayer(trackSource);//获取轨迹数据后展示小车移动效果 }); var trackLine = new ol.layer.Vector({ source: trackSource, style: new ol.style.Style({ stroke: new ol.style.Stroke({ color: "#0096c7", width: 5 }) }) }); map.addLayer(trackLine); ``` 在获取到轨迹数据后,就可以对其进行插值,增加移动点图层,设置图标样式。 ```javascript var distance = 5;//步长 var totalTime = 60*1000; //总时间 var srcUri = "./img/car.png"; function showCarLayer(source){ //设置汽车图标样式 var carStyle = new ol.style.Style({ image: new ol.style.Icon({ src: srcUri, scale: 0.2, offset: [-18,40] }) }); //获取轨迹线段的所有坐标点数组 var coordinates = source.getFeatures()[0].getGeometry().getCoordinates(); var firstPoint = new ol.geom.Point(coordinates[0]); var focusFeature = new ol.Feature(firstPoint); focusFeature.setStyle(carStyle); var carLayer = new ol.layer.Vector({ source: new ol.source.Vector({ features:[focusFeature] }) }); map.addLayer(carLayer); //计算轨迹点点集 var pointArr = []; pointArr.push(coordinates[0]); for(var i=1;i distance){ var ratio = distance/dd; var endX = pointArrLast[0] + ratio*(coordinates[i][0] - pointArrLast[0]); var endY = pointArrLast[1] + ratio*(coordinates[i][1] - pointArrLast[1]); pointArr.push([endX,endY]); i--; }else{ pointArr.push(coordinates[i]); } } //展示小车移动 var stopTime = totalTime/pointArr.length; for(let j=1;j= startx && endy >= starty)//第一象限 { return -tan; } else if (endx > startx && endy < starty)//第四象限 { return tan; } else if (endx < startx && endy > starty)//第二象限 { return tan - Math.PI; } else { return Math.PI - tan; //第三象限 } } ```