说明:

我的需求是需要实现轨迹播放/暂停/重新播放/从点击处播放,因此封装了一个类

解决方案:

1、初始化:主要是处理一下图层以及数据,通过插值构造一个全局数组

    /**
* @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);
});
})();

2、播放方法:首先跳转到轨迹范围;新建一个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);
}

3、暂停/播放:这里设置了一个变量isRun控制,如果false则timer里直接返回,不执行绘制

    /**
* 暂停/继续播放
* @param {Boolean} isRun 返回暂停还是播放
*/
this.paused = function () {
//如果没有定时器,则不暂停
if (this.timer) {
isRun = !isRun;
return isRun;
}
else {
return null;
}
};

4、重新播放:清空上一个计时器,重新播放

/**
* 重新播放
*/
this.restart = function () {
clearInterval(this.timer);
isRun = true;
// this._animationLineLayer.getSource().clear();
// this._animationPointLayer.getSource().clear();
this.play(that.speed); }

5、点击处重新播放:这个select事件放在初始化时注册完成的;使用了数组filter方法过滤数组,并控制全局游标replayIndex;找到播放到的数组元素,从那里开始

        //注册点击查询事件,点击暂停/从此播放
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);
});

6、提速/减速:这里控制计时器的速度,其实还有另一种做法就是控制插值的密度。

    /**
* 提速
*/
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;
};

7、最后附上全部代码(需要改造才能使用,因为这里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++;
}
}
};

Openlayers 实现轨迹播放/暂停/重新播放/从点击处播放/提速/减速的更多相关文章

  1. Cocos2d-x中背景音乐播放暂停与继续

    背景音乐播放暂停与继续似乎我们很少使用,事实上也正是如此,背景音乐播放暂停与继续实例代码如下: SimpleAudioEngine::getInstance()->pauseBackground ...

  2. 31.JS实现控制HTML5背景音乐播放暂停

    实现控制网站背景音乐的播放暂停在html5中是非常容易和简单的,仅仅几行代码即可实现.首先在网页中嵌入背景音乐,html5代码为: <script src="http://wuover ...

  3. JavaScript多个h5播放器video,点击一个播放其他暂停

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. js-音乐播放器,播放|暂停|滑块的功能

    音乐播放器,播放|暂停|滑块的功能 document.addEventListener('DOMContentLoaded', function loaded(event) { var audio = ...

  5. HTML5-video(播放暂停视频;打开关闭声音;进度条)

    <!DOCTYPE html> <html> <head> <title>HTML5-video(播放暂停视频:打开关闭声音:进度条)</titl ...

  6. Lily_music 网页音乐播放器 -可搜索(附歌词联动播放效果解说)

    博客地址:https://ainyi.com/59 写在前面 这是我今年(2018)年初的小项目,当时也是手贱,不想用别的播放器,想着做一个自己的网页播放器,有个歌曲列表.可关键词搜索.歌词滚动播放的 ...

  7. javascript JSMpeg.js 播放视频解决不用全屏也能播放(也支持自动播放哦)

    javascript JSMpeg.js 播放视频解决不用全屏也能播放(也支持自动播放哦) 缺陷就是 因为采用的是 MPEG1解码器 所以清晰度有点低 做直播可以考虑下 如果要清晰度高点 可以采取序列 ...

  8. HTML5播放暂停音乐

    查看效果:http://hovertree.com/code/jquery/ueyf7gn4.htm 代码如下: <!DOCTYPE html> <html> <head ...

  9. 使用jQuery播放/暂停 HTML5视频

    文章来自:http://blog.okbase.net/jquery2000/archive/4485.html 我尝试用jQuery控制HTML5视频,两个视频分别在两个tab中,我希望点中tab后 ...

随机推荐

  1. 【Bug】解决 SpringBoot Artifact contains illegal characters 错误

    解决 SpringBoot  Artifact contains illegal characters错误 错误原因:Artifact包含非法字符(大写字母) 解决方法:将Artifact名称改成小写 ...

  2. 美团 iOS 端开源框架 Graver 在动态化上的探索与实践

    近些年,移动端动态化技术可谓是“百花齐放”,其中的渲染性能也是动态化技术一直在探索.研究的课题.美团的开源框架 Graver 也为解决动态化框架的渲染性能问题提供了一种新思路:关于布局,我们可以采用“ ...

  3. Java基础(二十六)Java IO(3)字节流(Byte Stream)

    字节流是以字节为单位来处理数据的,由于字节流不会对数据进行任何转换,因此用来处理二进制的数据. 一.InputStream类与OutputStream类 1.InputStream类是所有字节输入流的 ...

  4. MarkDown的常用语法

    个人比较喜欢Markdown的语法,常用来做一些笔记,下面就简单介绍一下它的语法. 概览 宗旨 Markdown 的目标是实现「易读易写」. 可读性,无论如何,都是最重要的.一份使用 Markdown ...

  5. 零基础攻略!如何使用kubectl和HPA扩展Kubernetes应用程序

    现如今,Kubernetes已经完全改变了软件开发方式.Kubernetes作为一个管理容器化工作负载及服务的开源平台,其拥有可移植.可扩展的特性,并促进了声明式配置和自动化,同时它还证明了自己是管理 ...

  6. MIT线性代数:9.线性相关,基,维数。

  7. 题解 【洛谷】AT654

    题解 AT654 [役人[错题已隐藏]] 此题题面没搬过来, 会日语的dalao可以自行去ATCoder查看. 给出此题的JavaAC代码: public class Main { public st ...

  8. 深入理解C#第三版部分内容

     最近,粗略的读了<深入理解C#(第三版)>这本技术书,书中介绍了C#不同版本之间的不同以及新的功能. 现在将部分摘录的内容贴在下面,以备查阅. C#语言特性: 1.C#2.0 C#2的主 ...

  9. python学习之【第五篇】:Python中的元组及其所具有的方法

    1.前言 Python的元组(tuple)与列表很相似,不同之处在于元组不能被修改,即元组一旦创建,就不能向元组中的增加新元素,不能删除元素中的元素,更不能修改元组中元素.但是元组可以访问任意元素,可 ...

  10. Docker变量的相关总结

    一.AVG与ENV 1.在Dockerfile中,使用ARG与ENV的区别 ARG:ARG定义的变量用于构建Docker镜像,在通过build把Dockerfile构建成镜像后,ARG定义的变量便不在 ...