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 () {
        var me = this;
        //定位到轨迹范围
        var featureExtent = new ol.Feature({
            geometry: new ol.geom.LineString(this._linePatrolArray)
        });
        this._map.encmap.getView().fit(featureExtent.getGeometry().getExtent());

        //如果连续定时器没有清空,则清空定时器
        if (this.timer != null) {
            clearInterval(this.timer);
            if (this._animationLineLayer.getSource() != null) {
                this._animationLineLayer.getSource().clear();
            }
            if (this._animationPointLayer.getSource() != null) {
                this._animationPointLayer.getSource().clear();
            }
        }
        replayIndex = 0;
        this.timer = setInterval(function () {
            // console.log(me.timer);
            //暂停
            if (!isRun) {
                return;
            }
            //播放完成,停止定时器
            if (replayIndex > me._pointArray.length - 2) {
                clearInterval(me.timer);
                return;
            }
            //创建轨迹线
            var line = new ol.Feature({
                geometry: new ol.geom.LineString([me._pointArray[replayIndex], me._pointArray[++replayIndex]])
            });
            line.set("arrIndex", replayIndex);
            //设置线的样式
            line.setStyle(that._strokestyle);
            me._animationLineLayer.getSource().addFeature(line);

            //创建轨迹点
            var point = new ol.Feature({
                geometry: new ol.geom.Point(me._pointArray[replayIndex])
            });
            point.setStyle(that._Iconstyle);
            me._animationPointLayer.getSource().clear();
            me._animationPointLayer.getSource().addFeature(point);
        }, 40);
    }

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

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、最后附上全部代码(需要改造才能使用,因为这里map以及findlayerbyid都是封装好的方法)

RoadLineShow = function (_map, animationLineLayer, animationPointLayer, linePatrolArray, strokestyle, Iconstyle) {
    var that = this;
    var timer = this.timer;//连续定时器
    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 () {
        //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();
            }
        }
        replayIndex = 0;
        this.timer = setInterval(function () {
            // console.log(me.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);
        }, 40);
    }
    /**
     * 重新播放
     */
    this.restart = function () {
        clearInterval(this.timer);
        isRun = true;
        // this._animationLineLayer.getSource().clear();
        // this._animationPointLayer.getSource().clear();
        this.play();
    }

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

    //插入临时点,每两个点之间插入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++;
        }
    }
};

7、调用方法

//初始化
//参数为:地图对象/线图层/点图层/坐标数组/线样式/点样式
road = new RoadLineShow(Map, animationLineLayer, animationPointLayer, Coordinates, stoke, circle);

//播放
road.play();

//暂停/播放
var state = road.paused();
if (state) {
   document.getElementById("btnPaused").innerHTML = "暂停";
}
else {
   document.getElementById("btnPaused").innerHTML = "继续";
}

//重新播放
road.restart();

 

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
抱歉,作为AI语言模型,我无法为您生成实际可用的代码。但是,我可以为您提供一些基本步骤和示例代码,以帮助您实现此功能。 步骤: 1. 获取车辆轨迹数据。可以从GPS设备、行车记录仪等设备中获取车辆轨迹数据。也可以从第三方数据提供商获取数据。 2. 在OpenLayers中创建地图,并将地图中心设置为北京。 ```javascript var map = new ol.Map({ target: 'map', layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }) ], view: new ol.View({ center: ol.proj.fromLonLat([116.4074, 39.9042]), //设置地图中心为北京 zoom: 10 //设置地图缩放级别 }) }); ``` 3. 将车辆轨迹数据添加到地图中。可以使用OpenLayers的Vector Layer来显示车辆轨迹数据。 ```javascript var vectorLayer = new ol.layer.Vector({ source: new ol.source.Vector({ features: [] }), style: new ol.style.Style({ stroke: new ol.style.Stroke({ color: 'blue', width: 2 }) }) }); map.addLayer(vectorLayer); // 将车辆轨迹数据添加到Vector Layer中 var points = [[116.4074, 39.9042], [121.4737, 31.2304], ...]; //车辆轨迹数据 var features = []; for (var i = 0; i < points.length; i++) { var point = ol.proj.fromLonLat(points[i]); var feature = new ol.Feature({ geometry: new ol.geom.Point(point) }); features.push(feature); } vectorLayer.getSource().addFeatures(features); ``` 4. 播放车辆轨迹。可以使用OpenLayers的Animation来实现车辆轨迹播放效果。 ```javascript var duration = 2000; //每个点之间的动画时间 var start = new Date().getTime(); var pan = ol.animation.pan({ duration: duration, source: map.getView().getCenter(), start: start }); var zoom = ol.animation.zoom({ duration: duration, resolution: map.getView().getResolution(), start: start }); var animating = false; var speed = 100; //每秒移动的点数 function startAnimation() { if (animating) { stopAnimation(); } else { animating = true; vectorLayer.getSource().clear(); var features = vectorLayer.getSource().getFeatures(); var geom = features[0].getGeometry(); var coords = geom.getCoordinates(); var count = coords.length; var index = 0; var interval = duration / (count / speed); var timer = setInterval(function() { var elapsedTime = new Date().getTime() - start; var fraction = elapsedTime / duration; if (fraction >= 1) { clearInterval(timer); animating = false; } var currentCoord = coords[Math.round((count - 1) * fraction)]; var feature = new ol.Feature({ geometry: new ol.geom.Point(currentCoord) }); vectorLayer.getSource().addFeature(feature); map.getView().setCenter(currentCoord); map.getView().setZoom(14); }, interval); } } function stopAnimation() { animating = false; } document.getElementById('start-button').addEventListener('click', startAnimation); document.getElementById('stop-button').addEventListener('click', stopAnimation); ``` 以上是基本的示例代码,您需要根据实际情况进行适当的修改和调整。同时,需要注意的是,车辆轨迹数据的获取和使用需要遵守相关法律法规和隐私政策。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值