Openlayers 实现轨迹播放/暂停/重新播放/从点击处播放/提速/减速
说明:
我的需求是需要实现轨迹播放/暂停/重新播放/从点击处播放,因此封装了一个类
解决方案:
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 实现轨迹播放/暂停/重新播放/从点击处播放/提速/减速的更多相关文章
- Cocos2d-x中背景音乐播放暂停与继续
背景音乐播放暂停与继续似乎我们很少使用,事实上也正是如此,背景音乐播放暂停与继续实例代码如下: SimpleAudioEngine::getInstance()->pauseBackground ...
- 31.JS实现控制HTML5背景音乐播放暂停
实现控制网站背景音乐的播放暂停在html5中是非常容易和简单的,仅仅几行代码即可实现.首先在网页中嵌入背景音乐,html5代码为: <script src="http://wuover ...
- JavaScript多个h5播放器video,点击一个播放其他暂停
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- js-音乐播放器,播放|暂停|滑块的功能
音乐播放器,播放|暂停|滑块的功能 document.addEventListener('DOMContentLoaded', function loaded(event) { var audio = ...
- HTML5-video(播放暂停视频;打开关闭声音;进度条)
<!DOCTYPE html> <html> <head> <title>HTML5-video(播放暂停视频:打开关闭声音:进度条)</titl ...
- Lily_music 网页音乐播放器 -可搜索(附歌词联动播放效果解说)
博客地址:https://ainyi.com/59 写在前面 这是我今年(2018)年初的小项目,当时也是手贱,不想用别的播放器,想着做一个自己的网页播放器,有个歌曲列表.可关键词搜索.歌词滚动播放的 ...
- javascript JSMpeg.js 播放视频解决不用全屏也能播放(也支持自动播放哦)
javascript JSMpeg.js 播放视频解决不用全屏也能播放(也支持自动播放哦) 缺陷就是 因为采用的是 MPEG1解码器 所以清晰度有点低 做直播可以考虑下 如果要清晰度高点 可以采取序列 ...
- HTML5播放暂停音乐
查看效果:http://hovertree.com/code/jquery/ueyf7gn4.htm 代码如下: <!DOCTYPE html> <html> <head ...
- 使用jQuery播放/暂停 HTML5视频
文章来自:http://blog.okbase.net/jquery2000/archive/4485.html 我尝试用jQuery控制HTML5视频,两个视频分别在两个tab中,我希望点中tab后 ...
随机推荐
- C# 表达式树 Expression
表达式树是定义代码的数据结构. 它们基于编译器用于分析代码和生成已编译输出的相同结构. 几种常见的表达式 BinaryExpression 包含二元运算符的表达式 BinaryExpression b ...
- 【Bug】解决 SpringBoot Artifact contains illegal characters 错误
解决 SpringBoot Artifact contains illegal characters错误 错误原因:Artifact包含非法字符(大写字母) 解决方法:将Artifact名称改成小写 ...
- 微信小程序中的canvas基础应用
学了东西还是要记录一下,刚入职的小萌新啊,运气好分到一个项目不是很急的组原以为时间多了可以多学一些东西,但是发现好像不知道从哪里开始下手,我太南了.... 看旁边的实习生同事一直在搞canvas,自己 ...
- SoapUI 关联之Property Transfer、JSONPath、Xpath
进行接口功能测试过程中,经常会碰到,需要获取到上一个请求响应结果中数据,传递到下一个请求中来使用.在soapui中我们通过Property Transfer来实现. 1.Property Transf ...
- Kafka权威指南阅读笔记(第五章)
Kafka Broker kafka 第一个启动的Broker在ZooKeeper中创建一个临时节点/controller,让自己成为控制器.其他Broker启动后在控制器节点上创建Watch对象,便 ...
- JavaScript设计模式(代理模式)
一.简单的单例模式: 1.未使用代理模式的情况:小明直接给女神送花 var Flower = function() {} var xiaoming = { sendFlower: function( ...
- Flask:Flask的模板系统和静态文件
1.Flask模板系统 Django框架有自己独立的模板系统,而Flask是没有的,Flask默认采用jinjia2模板系统,jinjia2是仿写Django模板系统的一个第三方模块,但性能上要比Dj ...
- shell 队列实现线程并发控制
需求:并发检测1000台web服务器状态(或者并发为1000台web服务器分发文件等)如何用shell实现? 方案一:(这应该是大多数人都第一时间想到的方法吧) 思路:一个for循环1000次,顺序执 ...
- 如何将excel文件导入testlink
Step 1 按照excel模板设计测试用例,其中优先级的定义为: 数值 定义 1 LOW 2 MEDIUM 3 HIGH Step 2 执行脚本,将excel转换成xml: 脚本 备注 包含:exc ...
- Android 4.2 获取应用缓存接口变化
PackageManager.getPackageSizeInfo(String packageName, IPackageStatsObserver observer)不可用,改为PackageMa ...