個人需求是須要實現軌跡播放/暫停/從新播放/從點擊處播放,所以封裝了一個類數組
一、初始化:主要是處理一下圖層以及數據,經過插值構造一個全局數組函數
/** * @description 初始化軌跡 */ (function init() { //地圖容器 that._map = _map; //軌跡線圖層 that._animationLineLayer = animationLineLayer; //軌跡點圖層 that._animationPointLayer = animationPointLayer; //軌跡樣式 that._strokestyle = strokestyle; //軌跡樣式 that._Iconstyle = Iconstyle; //軌跡點集(帶插值) that._pointArray = []; //軌跡點集(不帶插值) that._linePatrolArray = linePatrolArray; //設置圖層id animationLineLayer.set('layerId', 'animationLineLayer'); animationPointLayer.set('layerId', 'animationPointLayer'); //沒有傳座標點過來就返回 if (linePatrolArray.length == 0) return; //若是連續定時器沒有清空,則清空定時器 clearInterval(this.timer); //移除路徑圖層 if (_map.findLayerByID("animationLineLayer") != null) { _map.encmap.removeLayer(_map.findLayerByID("animationLineLayer")); } //移除動畫點的圖層 if (_map.findLayerByID("animationPointLayer") != null) { _map.encmap.removeLayer(_map.findLayerByID("animationPointLayer")); } //記錄插值後的全部軌跡點,給pointArray for (var i = 0; i < linePatrolArray.length - 1; i++) { interpolation(linePatrolArray[i], linePatrolArray[i + 1]); } var curentLineLayer = _map.findLayerByID("animationLineLayer"); var curentPointLayer = _map.findLayerByID("animationPointLayer"); //若是此時map對象中有路徑animationLineLayer圖層 if (curentLineLayer != null) { //若是此時路徑animationLineLayer圖層沒有清空,清空裏面的內容 if (curentLineLayer.getSource() != null) { curentLineLayer.getSource().clear(); } } else { //若是此時map對象中沒有路徑圖層,添加路徑animationLineLayer圖層 _map.encmap.addLayer(animationLineLayer); } //若是此時map對象中有移動動畫點animationPointLayer圖層 if (curentPointLayer != null) { if (curentPointLayer.getSource() != null) { //清空動畫點animationPointLayer圖層的內容 curentPointLayer.getSource().clear(); } } else { //若是此時map對象中沒有移動點圖層,添加移動點animationPointLayer圖層 _map.encmap.addLayer(animationPointLayer); } //註冊點擊查詢事件,點擊暫停/今後播放 let selecthover = new ol.interaction.Select({ condition: ol.events.condition.click, layers: [animationLineLayer] }); selecthover.set("arrPoints", that._pointArray); // selecthover.set("tmpPoints", that._pointArray); selecthover.set("_strokestyle", that._strokestyle); selecthover.set("_Iconstyle", that._Iconstyle); selecthover.set("_animationLineLayer", that._animationLineLayer); selecthover.set("_animationPointLayer", that._animationPointLayer); _map.encmap.addInteraction(selecthover); var me = that; //查詢結果 selecthover.on("select", function (evt) { if (evt.selected[0] == null) return; //取消選中要素高亮 this.getFeatures().clear(); //暫停/繼續 //isRun = !isRun; // console.log(replayIndex); //從點擊處開始播放 isRun = true; replayIndex = evt.selected[0].get("arrIndex"); var tmpPointsArray = this.getProperties()["arrPoints"]; var tmpPoints = this.getProperties()["tmpPoints"]; var _strokestyle = this.getProperties()["_strokestyle"]; var _Iconstyle = this.getProperties()["_Iconstyle"]; var _animationLineLayer = this.getProperties()["_animationLineLayer"]; var _animationPointLayer = this.getProperties()["_animationPointLayer"]; //保留走完的線 _animationLineLayer.getSource().clear(); // tmpPointsArray.filter(e => e <= replayIndex); var pts = []; pts.push(tmpPointsArray); pts = pts[0]; for (var m = 0; m <= replayIndex - 1; m++) { //建立軌跡線 var line = new ol.Feature({ geometry: new ol.geom.LineString([pts[m], pts[m + 1]]) }); line.set("arrIndex", m); // //設置線的樣式 line.setStyle(_strokestyle); _animationLineLayer.getSource().addFeature(line); } //添加點擊點 var clickPt = new ol.Feature({ geometry: new ol.geom.Point(tmpPointsArray[replayIndex]) }); clickPt.setStyle(_Iconstyle); _animationPointLayer.getSource().clear(); _animationPointLayer.getSource().addFeature(clickPt); }); })();
二、播放方法:首先跳轉到軌跡範圍;新建一個timer定時器,並控制播放完全部軌跡點後清除定時器;用lineString函數傳入首尾座標,完成繪線。動畫
//動畫播放 this.play = function (_speed) { //var me = this; //定位到軌跡範圍 var featureExtent = new ol.Feature({ geometry: new ol.geom.LineString(that._linePatrolArray) }); that._map.encmap.getView().fit(featureExtent.getGeometry().getExtent()); //若是連續定時器沒有清空,則清空定時器 if (this.timer != null) { clearInterval(this.timer); if (that._animationLineLayer.getSource() != null) { that._animationLineLayer.getSource().clear(); } if (that._animationPointLayer.getSource() != null) { that._animationPointLayer.getSource().clear(); } } //播放速度 that.speed = _speed; //計時器默認40ms if (!that.speed) { that.speed = 40; } replayIndex = 0; this.timer = setInterval(function () { console.log(that.timer); //暫停 if (!isRun) { return; } //播放完成,中止定時器 if (replayIndex > that._pointArray.length - 2) { clearInterval(that.timer); return; } //建立軌跡線 var line = new ol.Feature({ geometry: new ol.geom.LineString([that._pointArray[replayIndex], that._pointArray[++replayIndex]]) }); line.set("arrIndex", replayIndex); //設置線的樣式 line.setStyle(that._strokestyle); that._animationLineLayer.getSource().addFeature(line); //建立軌跡點 var point = new ol.Feature({ geometry: new ol.geom.Point(that._pointArray[replayIndex]) }); point.setStyle(that._Iconstyle); that._animationPointLayer.getSource().clear(); that._animationPointLayer.getSource().addFeature(point); }, that.speed); }
三、暫停/播放:這裏設置了一個變量isRun控制,若是false則timer裏直接返回,不執行繪製this
/** * 暫停/繼續播放 * @param {Boolean} isRun 返回暫停仍是播放 */ this.paused = function () { //若是沒有定時器,則不暫停 if (this.timer) { isRun = !isRun; return isRun; } else { return null; } };
四、從新播放:清空上一個計時器,從新播放spa
/** * 從新播放 */ this.restart = function () { clearInterval(this.timer); isRun = true; // this._animationLineLayer.getSource().clear(); // this._animationPointLayer.getSource().clear(); this.play(that.speed); }
五、點擊處從新播放:這個select事件放在初始化時註冊完成的;使用了數組filter方法過濾數組,並控制全局遊標replayIndex;找到播放到的數組元素,從那裏開始rest
//註冊點擊查詢事件,點擊暫停/今後播放 let selecthover = new ol.interaction.Select({ condition: ol.events.condition.click, layers: [animationLineLayer] }); selecthover.set("arrPoints", that._pointArray); // selecthover.set("tmpPoints", that._pointArray); selecthover.set("_strokestyle", that._strokestyle); selecthover.set("_Iconstyle", that._Iconstyle); selecthover.set("_animationLineLayer", that._animationLineLayer); selecthover.set("_animationPointLayer", that._animationPointLayer); _map.encmap.addInteraction(selecthover); var me = that; //查詢結果 selecthover.on("select", function (evt) { if (evt.selected[0] == null) return; //取消選中要素高亮 this.getFeatures().clear(); //暫停/繼續 //isRun = !isRun; // console.log(replayIndex); //從點擊處開始播放 isRun = true; replayIndex = evt.selected[0].get("arrIndex"); var tmpPointsArray = this.getProperties()["arrPoints"]; var tmpPoints = this.getProperties()["tmpPoints"]; var _strokestyle = this.getProperties()["_strokestyle"]; var _Iconstyle = this.getProperties()["_Iconstyle"]; var _animationLineLayer = this.getProperties()["_animationLineLayer"]; var _animationPointLayer = this.getProperties()["_animationPointLayer"]; //保留走完的線 _animationLineLayer.getSource().clear(); // tmpPointsArray.filter(e => e <= replayIndex); var pts = []; pts.push(tmpPointsArray); pts = pts[0]; for (var m = 0; m <= replayIndex - 1; m++) { //建立軌跡線 var line = new ol.Feature({ geometry: new ol.geom.LineString([pts[m], pts[m + 1]]) }); line.set("arrIndex", m); // //設置線的樣式 line.setStyle(_strokestyle); _animationLineLayer.getSource().addFeature(line); } //添加點擊點 var clickPt = new ol.Feature({ geometry: new ol.geom.Point(tmpPointsArray[replayIndex]) }); clickPt.setStyle(_Iconstyle); _animationPointLayer.getSource().clear(); _animationPointLayer.getSource().addFeature(clickPt); });
六、提速/減速:這裏控制計時器的速度,其實還有另外一種作法就是控制插值的密度。code
/** * 提速 */ this.faster = function () { clearInterval(this.timer); isRun = true; //若是速度小於10,則不容許再提速 if (that.speed > 10) { that.speed = that.speed - 1; } this.play(that.speed); return that.speed; }; /** * 減速 */ this.slower = function () { clearInterval(this.timer); isRun = true; that.speed = that.speed + 1; this.play(that.speed); return that.speed; };
七、最後附上所有代碼(須要改造才能使用,由於這裏map以及findlayerbyid都是封裝好的方法)對象
RoadLineShow = function (_map, animationLineLayer, animationPointLayer, linePatrolArray, strokestyle, Iconstyle) { var that = this; var timer = this.timer;//連續定時器 var speed = this.speed;//定時器速度 var ref;//斷續定時器 var j = 0; //播放與暫停標識 var isRun = true; /** * @description 初始化軌跡 */ (function init() { //地圖容器 that._map = _map; //軌跡線圖層 that._animationLineLayer = animationLineLayer; //軌跡點圖層 that._animationPointLayer = animationPointLayer; //軌跡樣式 that._strokestyle = strokestyle; //軌跡樣式 that._Iconstyle = Iconstyle; //軌跡點集(帶插值) that._pointArray = []; //軌跡點集(不帶插值) that._linePatrolArray = linePatrolArray; //設置圖層id animationLineLayer.set('layerId', 'animationLineLayer'); animationPointLayer.set('layerId', 'animationPointLayer'); //沒有傳座標點過來就返回 if (linePatrolArray.length == 0) return; //若是連續定時器沒有清空,則清空定時器 clearInterval(this.timer); //移除路徑圖層 if (_map.findLayerByID("animationLineLayer") != null) { _map.encmap.removeLayer(_map.findLayerByID("animationLineLayer")); } //移除動畫點的圖層 if (_map.findLayerByID("animationPointLayer") != null) { _map.encmap.removeLayer(_map.findLayerByID("animationPointLayer")); } //記錄插值後的全部軌跡點,給pointArray for (var i = 0; i < linePatrolArray.length - 1; i++) { interpolation(linePatrolArray[i], linePatrolArray[i + 1]); } var curentLineLayer = _map.findLayerByID("animationLineLayer"); var curentPointLayer = _map.findLayerByID("animationPointLayer"); //若是此時map對象中有路徑animationLineLayer圖層 if (curentLineLayer != null) { //若是此時路徑animationLineLayer圖層沒有清空,清空裏面的內容 if (curentLineLayer.getSource() != null) { curentLineLayer.getSource().clear(); } } else { //若是此時map對象中沒有路徑圖層,添加路徑animationLineLayer圖層 _map.encmap.addLayer(animationLineLayer); } //若是此時map對象中有移動動畫點animationPointLayer圖層 if (curentPointLayer != null) { if (curentPointLayer.getSource() != null) { //清空動畫點animationPointLayer圖層的內容 curentPointLayer.getSource().clear(); } } else { //若是此時map對象中沒有移動點圖層,添加移動點animationPointLayer圖層 _map.encmap.addLayer(animationPointLayer); } //註冊點擊查詢事件,點擊暫停/今後播放 let selecthover = new ol.interaction.Select({ condition: ol.events.condition.click, layers: [animationLineLayer] }); selecthover.set("arrPoints", that._pointArray); // selecthover.set("tmpPoints", that._pointArray); selecthover.set("_strokestyle", that._strokestyle); selecthover.set("_Iconstyle", that._Iconstyle); selecthover.set("_animationLineLayer", that._animationLineLayer); selecthover.set("_animationPointLayer", that._animationPointLayer); _map.encmap.addInteraction(selecthover); var me = that; //查詢結果 selecthover.on("select", function (evt) { if (evt.selected[0] == null) return; //取消選中要素高亮 this.getFeatures().clear(); //暫停/繼續 //isRun = !isRun; // console.log(replayIndex); //從點擊處開始播放 isRun = true; replayIndex = evt.selected[0].get("arrIndex"); var tmpPointsArray = this.getProperties()["arrPoints"]; var tmpPoints = this.getProperties()["tmpPoints"]; var _strokestyle = this.getProperties()["_strokestyle"]; var _Iconstyle = this.getProperties()["_Iconstyle"]; var _animationLineLayer = this.getProperties()["_animationLineLayer"]; var _animationPointLayer = this.getProperties()["_animationPointLayer"]; //保留走完的線 _animationLineLayer.getSource().clear(); // tmpPointsArray.filter(e => e <= replayIndex); var pts = []; pts.push(tmpPointsArray); pts = pts[0]; for (var m = 0; m <= replayIndex - 1; m++) { //建立軌跡線 var line = new ol.Feature({ geometry: new ol.geom.LineString([pts[m], pts[m + 1]]) }); line.set("arrIndex", m); // //設置線的樣式 line.setStyle(_strokestyle); _animationLineLayer.getSource().addFeature(line); } //添加點擊點 var clickPt = new ol.Feature({ geometry: new ol.geom.Point(tmpPointsArray[replayIndex]) }); clickPt.setStyle(_Iconstyle); _animationPointLayer.getSource().clear(); _animationPointLayer.getSource().addFeature(clickPt); }); })(); /** * 提供座標數組,展現軌跡 * @param _map 實例化map對象 * @param Coordinates 座標數組例如[123458.421,123432] * @param lineStyle 軌跡的式樣 * @returns {ol.layer.Vector} 返回一個layer實例 */ this.getRoadLineLayer = function (_map, Coordinates, lineStyle) { var route = new ol.geom.LineString(Coordinates); //獲取直線的座標 var Featureroute = new ol.Feature({ type: 'route', geometry: route }); var routeFeature = [Featureroute]; var routeSource = new ol.source.Vector( { features: routeFeature } ); var vectorLayer = new ol.layer.Vector({ source: routeSource, style: lineStyle }); var myFeatureExtent = vectorLayer.getSource().getExtent(); if (myFeatureExtent != null) { let view = _map.encmap.getView(); //改變視圖view view.fit(myFeatureExtent); } return vectorLayer; }; //動畫播放 this.play = function (_speed) { //var me = this; //定位到軌跡範圍 var featureExtent = new ol.Feature({ geometry: new ol.geom.LineString(that._linePatrolArray) }); that._map.encmap.getView().fit(featureExtent.getGeometry().getExtent()); //若是連續定時器沒有清空,則清空定時器 if (this.timer != null) { clearInterval(this.timer); if (that._animationLineLayer.getSource() != null) { that._animationLineLayer.getSource().clear(); } if (that._animationPointLayer.getSource() != null) { that._animationPointLayer.getSource().clear(); } } //播放速度 that.speed = _speed; //計時器默認40ms if (!that.speed) { that.speed = 40; } replayIndex = 0; this.timer = setInterval(function () { console.log(that.timer); //暫停 if (!isRun) { return; } //播放完成,中止定時器 if (replayIndex > that._pointArray.length - 2) { clearInterval(that.timer); return; } //建立軌跡線 var line = new ol.Feature({ geometry: new ol.geom.LineString([that._pointArray[replayIndex], that._pointArray[++replayIndex]]) }); line.set("arrIndex", replayIndex); //設置線的樣式 line.setStyle(that._strokestyle); that._animationLineLayer.getSource().addFeature(line); //建立軌跡點 var point = new ol.Feature({ geometry: new ol.geom.Point(that._pointArray[replayIndex]) }); point.setStyle(that._Iconstyle); that._animationPointLayer.getSource().clear(); that._animationPointLayer.getSource().addFeature(point); }, that.speed); } /** * 從新播放 */ this.restart = function () { clearInterval(this.timer); isRun = true; // this._animationLineLayer.getSource().clear(); // this._animationPointLayer.getSource().clear(); this.play(that.speed); } /** * 暫停/繼續播放 * @param {Boolean} isRun 返回暫停仍是播放 */ this.paused = function () { //若是沒有定時器,則不暫停 if (this.timer) { isRun = !isRun; return isRun; } else { return null; } }; /** * 提速 */ this.faster = function () { clearInterval(this.timer); isRun = true; //若是速度小於10,則不容許再提速 if (that.speed > 10) { that.speed = that.speed - 1; } this.play(that.speed); return that.speed; }; /** * 減速 */ this.slower = function () { clearInterval(this.timer); isRun = true; that.speed = that.speed + 1; this.play(that.speed); return that.speed; }; //插入臨時點,每兩個點之間插入39個點 function interpolation(pointA, pointB, speed) { var tmp = []; if (speed == undefined) { speed = 1; } speed = speed - 0.5; //不能大於播放速度 var count = Math.abs(speed) * 25; var pointA_X = pointA[0]; var pointA_Y = pointA[1]; var pointB_X = pointB[0]; var pointB_Y = pointB[1]; var disX = (pointB_X - pointA_X) / count; var disY = (pointB_Y - pointA_Y) / count; var i = 0; var x_y_point = []; while (i <= count) { var x = pointA_X + i * disX; var y = pointA_Y + i * disY; that._pointArray.push([x, y]); i++; } } };