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后 ...
随机推荐
- JDK路径配置,tomcat可以直接启动
path classpath java_home 修改tomcat配置文件,直接写入jdk路径,不推荐
- Linux对目录操作命令
cd /home 进入 '/ home' 目录 cd .. 返回上一级目录 cd ../.. 返回上两级目录 cd 进入个人的主目录 cd ~u ...
- Vultr新用户充值送50刀
充值送50刀 活动还是可以的,充个10刀,适合用来当测试服,按时间计费
- Kafka权威指南阅读笔记(第五章)
Kafka Broker kafka 第一个启动的Broker在ZooKeeper中创建一个临时节点/controller,让自己成为控制器.其他Broker启动后在控制器节点上创建Watch对象,便 ...
- 利用 Ansiable 自动化部署 Veeam Backup & Replication 9.5U4b
利用 Ansiable 自动化部署 Veeam Backup & Replication 9.5U4b 前言 上周出差期间接到一个做CMP(云管平台)Partner的需求,要在无人值守的安装 ...
- 网页开发利用jq自定义鼠标右击事件
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- 通过Value获取Map中的键值Key的四种方法
1 简介 我们都知道Map是存放键值对<Key,Value>的容器,知道了Key值,使用方法Map.get(key)能快速获取Value值.然而,有的时候我们需要反过来获取,知道Value ...
- [考试反思]1018csp-s模拟测试78(lrd day2) :规律
zkt没素质果然考炸了! 但是他考炸了和我一个分 这场的状态是真的不好,T3比较简单但没有做,一直干T2结果还是跪了 T1的哈希写挂了,模数比int大了结果一乘就炸long long了. 调了一个小时 ...
- GitHub_Hexo_Next 搭建博客
利用最新版本的 hexo+next 重构了个人博客,下面简单记录了搭建博客的完整过程: 一.环境准备 1.安装 Node.js 2.安装 Git 3.注册 Github 账号 二.在GitHub上创建 ...
- 『题解』洛谷P4016 负载平衡问题
title: categories: tags: - mathjax: true --- Problem Portal Portal1:Luogu Portal2: LibreOJ Descripti ...