基于openlayers完成车辆轨迹回放 暂停 继续 变色 弹框等功能demo

基于openlayers完成车辆轨迹回放 暂停 继续 变色 弹框等功能demo

为了方便日后查看 做个简单记录
运动很简单 官方demo里就有 但是官方demo里面没有暂停功能 这里研究完网上代码 大家都用的定时器 我也就抄过来了 在每次调用后 重新打小车 popup框的位置 重新绘制黄线(小车已经走过的线)和绿线(未走过的线) popup框可以传入 小车当前动态 反正挺简单的。
代码拿过去是不能直接用的 因为地图需要vpn 自己换一下 下面方法 由于封装过 id换成ol就行 其他的 直接cv。
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>WMTS</title>
    <script src="js/zy_index.js"></script>
    <!-- 引入样式 -->
    <!-- <link rel="stylesheet" href="element 2.12.0/index.css" /> -->
    <!-- 引入组件库 -->
    <!-- <script src="element 2.12.0/index.js"></script> -->
    <style>
        html,
        body {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
        }

        #map {
            width: 100%;
            height: 100%;
            position: absolute;
        }

        #menu {
            text-align: center;
            width: 100%;
            padding: 5px 10px;
            font-size: 14px;
            font-family: "微软雅黑";
            left: 10px;
        }

        .ol-popup {
            position: absolute;
            -webkit-filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2));
            filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2));
            padding: 15px;
            border-radius: 3px;
            border: solid 1px #A0A0A5;
            background-color: #eeefed;
            color: #3b5373;
            bottom: 12px;
            left: -50px;
            box-shadow: 0px 5px 9px #8A8A8A;
        }

        .ol-popup:after,
        .ol-popup:before {
            top: 100%;
            border: solid transparent;
            content: " ";
            height: 0;
            width: 0;
            position: absolute;
            pointer-events: none;
        }

        .ol-popup:after {
            border-top-color: #eeefed;
            border-width: 10px;
            left: 48px;
            margin-left: -10px;
        }

        .ol-popup:before {
            border-top-color: #eeefed;
            left: 48px;
            margin-left: -11px;
        }

        .ol-popup-closer {
            text-decoration: none;
            position: absolute;
            top: 2px;
            right: 8px;
        }

        .ol-popup-closer:after {
            content: "✖";
            color: #333;
        }
    </style>
</head>

<body>
    <div id="menu">
        <label for="speed">
            speed:&nbsp;
            <input id="speed" type="range" min="10" max="999" step="10" value="60">
        </label>
        <button id="start-animation">开始</button>
        <button id="pause-animation">暂停</button>
        <button id="continue-animation">继续</button>
        <button id="stop-animation">结束</button>
    </div>
    <div class="map" id="map">

        <div id="popup" class="ol-popup">
            <div>时间</div>
            <hr>
            <span id="popup-closer" class="ol-popup-closer"></span>
            <div id="popup-content">
            </div>
        </div>
    </div>
    <script>
        var map = new ld.Map({
            layers: [
                new ld.layer.Tile({
                    //实例化WMTS服务图层对象
                    source: new ld.source.WMTS({
                        url: "XXXXXXXXXX",
                        //WMTS服务基地址
                        layer: "BlueMap",
                        matrixSet: "CustomCRS4490ScaleBlueMap8", //投影坐标系设置矩阵
                        format: "image/png", //图片格式
                        projection: "EPSG:4326", //数据的投影坐标系
                        //瓦片网格对象
                        tileGrid: new ld.tilegrid.WMTS({
                            origin: [-180.0, 90.0], //网格原点
                            resolutions: [
                                0.010986328125000003,
                                0.005493164062500014,
                                0.002746582031250007,
                                0.0013732910156250035,
                                0.0006866455078125017,
                                0.00034332275390625087,
                                0.0001716613769531373,
                                0.0000858306884765568,
                                0.00004291534423826651,
                                0.000021457672119133256,
                                0.000010728836059578508,
                                0.000005364418029789254
                            ], //分辨率数组
                            matrixIds: [0, 1, 2, 3, 4, 5, 6, 7, 8,
                                9, 10,
                                11
                            ], //矩阵标识列表,与地图级数保持一致
                            tileSize: [256, 256], //瓦片尺寸
                        }),
                        style: 'default'
                    }),
                })
            ],
            controls: [new ld.control.Zoom()],
            target: "map", //地图容器div的ID
            view: new ld.View({
                center: [113.88170241890477, 34.49780059604906], //中心点
                matrixIds: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
                resolutions: [
                    0.010986328125000003,
                    0.005493164062500014,
                    0.002746582031250007,
                    0.0013732910156250035,
                    0.0006866455078125017,
                    0.00034332275390625087,
                    0.0001716613769531373,
                    0.0000858306884765568,
                    0.00004291534423826651,
                    0.000021457672119133256,
                    0.000010728836059578508,
                    0.000005364418029789254
                ], //分辨率数组
                projection: "EPSG:4326",
                zoom: 5, //地图层级
            }),
        });
        // 点的转向角度设置  new_p 上一点的坐标 old_p 下一点的坐标
        // function _map_p_rotation(new_p, old_p) {
        //     // 90度的PI值
        //     var pi_90 = Math.atan2(1, 0);
        //     // 当前点的PI值
        //     var pi_ac = Math.atan2(new_p[1] - old_p[1], new_p[0] - old_p[0]);
        //     return pi_90 - pi_ac;
        // }
        //构建一组离散化的点
        var Coordinates = new Array();
        var gpsPoints = zuobiaolist.data.gpsPoints;

        // console.log(zuobiaolist.data.gpsPoints)
        for (let i = 0; i < zuobiaolist.data.gpsPoints.length; i++) {
            Coordinates[i] = [zuobiaolist.data.gpsPoints[i].lng, zuobiaolist.data.gpsPoints[i].lat]

        }
        //将离散点构建成一条折线
        var route = new ld.geom.LineString(Coordinates);


        //获取直线的坐标
        var routeCoords = route.getCoordinates();
        console.log('routeCoords: ', routeCoords);
        var routeLength = routeCoords.length;

        var routeFeature = new ld.Feature({
            type: 'route',
            geometry: route
        });
        var geoMarker = new ld.Feature({
            type: 'geoMarker',
            geometry: new ld.geom.Point(routeCoords[0])
        });
        var startMarker = new ld.Feature({
            type: 'icon',
            geometry: new ld.geom.Point(routeCoords[0])
        });
        var endMarker = new ld.Feature({
            type: 'icon',
            geometry: new ld.geom.Point(routeCoords[routeLength - 1])
        });

        var styles = {
            'route': new ld.style.Style({
                //轨迹线
                stroke: new ld.style.Stroke({
                    width: 6,
                    color: [0, 212, 0, 1]
                })
            }),
            'icon': new ld.style.Style({
                image: new ld.style.Icon({
                    // anchor: [0.5, 1],
                    src: "./img/执法人员.png"
                })
            }),
            'geoMarker': new ld.style.Style({
                image: new ld.style.Icon( /** @type {olx.style.IconOptions} */ ({
                    // anchor: [0.5, 60],
                    anchorOrigin: 'top-right',
                    anchorXUnits: 'fraction',
                    anchorYUnits: 'pixels',
                    offsetOrigin: 'top-right', //偏移原点-偏移起点位置的方向
                    // offset:[0,10],
                    scale: 0.5, //图标缩放比例
                    // opacity: 0.75, //透明度
                    rotateWithView: false,
                    rotation: -Math.atan2(routeCoords[0][1] - routeCoords[1][1], routeCoords[0][
                        0
                    ] - routeCoords[1][0]), //旋转图片
                    src: './img/环卫车轨迹.png' //图标的url
                })),
            })
        };

        var animating = false;
        var speed;
        var now;
        var elapsedTime = 0;
        var speedInput = document.getElementById('speed')
        var startButton = document.getElementById('start-animation')
        var pauseButton = document.getElementById('pause-animation')
        var continueButton = document.getElementById('continue-animation')
        var stopButton = document.getElementById('stop-animation')
        var vectorLayer = new ld.layer.Vector({
            source: new ld.source.Vector({
                features: [routeFeature, geoMarker, startMarker, endMarker]
            }),
            style: function (feature) {
                //如果动画是激活的就隐藏geoMarker
                if (animating && feature.get('type') === 'geoMarker') {
                    return null;
                }
                return styles[feature.get('type')];
            }
        });
        map.addLayer(vectorLayer)
        //要素移动
        var moveFeature = function (event) {
            if (!vectorLayer.getVisible()) {
                vectorLayer.setVisible(true)
            }

            elapsedTime++ // elapsedTime 已过时间

            //通过增加速度,来获得lineString坐标
            // console.log('speed: ', speed);
            var index = Math.round(speed * elapsedTime / 60);

            if (index >= routeLength) {
                clearInterval(timer);
                return;
            }

            var x, y, rotation, carStyle;
            console.log('index: ', index);
            if (routeCoords[index] && routeCoords[index + 1]) {
                x = routeCoords[index][0] - routeCoords[index + 1][0];
                y = routeCoords[index][1] - routeCoords[index + 1][1];
                rotation = Math.atan2(y, x);
                //console.log("***********",rotation);
                // carStyle = new ol.style.Style({
                //     image: new ol.style.Icon({
                //         src: './img/环卫车轨迹.png', //图标的url,
                //         rotateWithView: false,
                //         rotation: Math.atan2(1, 0) - rotation,
                //         scale: 0.5,
                //     })
                // });

                // var currentPoint = new ld.geom.Point(routeCoords[index]);
                // var feature = new ld.Feature(currentPoint);

            } else {
                rotation = 0
            }
            carStyle = new ld.style.Style({
                image: new ld.style.Icon({
                    src: './img/环卫车轨迹.png', //图标的url,
                    rotateWithView: false,
                    rotation: Math.atan2(1, 0) - rotation,
                    scale: 0.5,
                })
            });
            var line = new ld.Feature({
                geometry: new ld.geom.LineString(routeCoords.slice(0, index + 1))
            })
            var lineStyle = new ld.style.Style({
                stroke: new ld.style.Stroke({
                    width: 6,
                    color: [237, 212, 0]
                })
            })
            line.setStyle(lineStyle)
            var line1 = new ld.Feature({
                geometry: new ld.geom.LineString(routeCoords.slice(index))
            })
            var lineStyle1 = new ld.style.Style({
                stroke: new ld.style.Stroke({
                    width: 6,
                    color: [0, 212, 0]
                })
            })
            line1.setStyle(lineStyle1)
            var currentPoint = new ld.geom.Point(routeCoords[index])
            // 添加矢量元素
            var feature = new ld.Feature(currentPoint)
            vectorLayer.getSource().clear()
            feature.setStyle(carStyle)
            
            // vectorLayer.getSource().addFeature(routeFeature)
            vectorLayer.getSource().addFeature(startMarker)
            vectorLayer.getSource().addFeature(endMarker)
            vectorLayer.getSource().addFeature(feature)
            vectorLayer.getSource().addFeature(line)
            vectorLayer.getSource().addFeature(line1)
            

            content.textContent = gpsPoints[index].gpsTime;
            popup.setPosition(routeCoords[index]);
            //继续动画效果
            map.render();


        };

        var timer;

        function startAnimation() {
            animating = true
            startTime = new Date().getTime()
            speed = speedInput.value
            // 隐藏geoMarker
            geoMarker.changed()
            // map.getView().setCenter([113.88170241890477, 34.49780059604906])
            // 添加事件,地图渲染时触发
            if (timer) {
                clearInterval(timer)
            }
            timer = setInterval(() => {
                moveFeature()
            }, 60)
            elapsedTime = 0
        }


        /**
         * @param {boolean}结束动画
         */
        function stopAnimation(ended) {
            clearInterval(timer)
            popup.setPosition(undefined); //未定义popup位置
            vectorLayer.getSource().clear()
            vectorLayer.getSource().addFeature(routeFeature)
            vectorLayer.getSource().addFeature(startMarker)
            vectorLayer.getSource().addFeature(endMarker)
        }

        function pauseAnimation() {
            clearInterval(timer)
            timerFlag = true
        }

        function continueAnimation() {
            if (timerFlag) {
                // map.getView().setCenter(Coordinates[0])
                // 添加事件,地图渲染时触发
                timer = setInterval(() => {
                    moveFeature()
                }, 60)
            }
            timerFlag = false
        }

        startButton.addEventListener('click', startAnimation, false);
        pauseButton.addEventListener('click', pauseAnimation, false)
        continueButton.addEventListener(
            'click',
            continueAnimation,
            false
        )
        stopButton.addEventListener('click', stopAnimation, false)

        /**
         * 实现popup的html元素
         */
        var container = document.getElementById('popup');
        var content = document.getElementById('popup-content');
        var closer = document.getElementById('popup-closer');

        /**
         * 在地图容器中创建一个Overlay
         */
        var popup = new ld.Overlay( /** @type {olx.OverlayOptions} */ ({
            element: container,
            autoPan: true,
            positioning: 'bottom-center',
            stopEvent: false,
            autoPanAnimation: {
                duration: 250
            }
        }));
        map.addOverlay(popup);

        /**
         * 在地图容器中创建一个Overlay
         */
        var popup = new ld.Overlay( /** @type {olx.OverlayOptions} */ ({
            element: container,
            autoPan: true,
            positioning: 'bottom-center',
            stopEvent: false,
            autoPanAnimation: {
                duration: 250
            }
        }));
        map.addOverlay(popup);

        /**
         * 添加关闭按钮的单击事件(隐藏popup)
         * @return {boolean} Don't follow the href.
         */
        closer.onclick = function () {
            popup.setPosition(undefined); //未定义popup位置
            closer.blur(); //失去焦点
            return false;
        };

        /**
         * 动态创建popup的具体内容
         * @param {string} title
         */
        // function addFeatrueInfo(info) {
        //     //新增div元素
        //     var elementDiv = document.createElement('div');
        //     elementDiv.className = "markerText";
        //     //elementDiv.innerText = info.att.text;
        //     setInnerText(elementDiv, info.att.text);
        //     content.appendChild(elementDiv); // 为content添加div子节点
        //     //新增img元素
        //     // var elementImg = document.createElement('img');
        //     // elementImg.className = "markerImg";
        //     // elementImg.src = info.att.imgURL;
        //     // content.appendChild(elementImg); // 为content添加img子节点
        // }
        /**
         * 动态设置元素文本内容(兼容)
         */
        function setInnerText(element, text) {
            if (typeof element.textContent == "string") {
                element.textContent = text;
            } else {
                element.innerText = text;
            }
        }

        /**
         * 为map添加点击事件监听,渲染弹出popup
         */
        map.on('click', function (evt) {
            var coordinate = evt.coordinate;
            //判断当前单击处是否有要素,捕获到要素时弹出popup
            var feature = map.forEachFeatureAtPixel(evt.pixel, function (feature, layer) {
                return feature;
            });
            if (feature) {
                content.innerHTML = ''; //清空popup的内容容器
                // addFeatrueInfo(featuerInfo); //在popup中加载当前要素的具体信息
                if (popup.getPosition() == undefined) {
                    popup.setPosition(coordinate); //设置popup的位置
                }
            }
        });
        /**
         * 为map添加鼠标移动事件监听,当指向标注时改变鼠标光标状态
         */
        map.on('pointermove', function (e) {
            var pixel = map.getEventPixel(e.originalEvent);
            var hit = map.hasFeatureAtPixel(pixel);
            map.getTargetElement().style.cursor = hit ? 'pointer' : '';
        });
    </script>
</body>

</html>
  • 2
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
抱歉,作为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); ``` 以上是基本的示例代码,您需要根据实际情况进行适当的修改和调整。同时,需要注意的是,车辆轨迹数据的获取和使用需要遵守相关法律法规和隐私政策。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值