• 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++;
            }
        }
    };
  • 相关阅读:
    Mycat学习笔记 第三篇. MySql 主从同步异常后,主从切换
    【转】MYSQL主从同步故障一例及解决过程!
    Mycat学习笔记 第二篇. MySql 读写分离与日志分析——主从多结点
    Mycat学习笔记 第一篇. MySql 读写分离与日志分析——主从单结点
    Leetcode 172 Factorial Trailing Zeroes
    Leetcode 7 Reverse Integer
    Leetcode 2 Add Two Numbers
    Leetcode 83 Remove Duplicates from Sorted List (快慢指针)
    Leetcode 141 Linked List Cycle(快慢指针)
    Leetcode 21 Merge Two Sorted Lists
  • 原文地址:https://www.cnblogs.com/giser-s/p/11855761.html
Copyright © 2020-2023  润新知