MapboxGL——marker轨迹动画效果,自定义速度。暂停继续轨迹运动

轨迹运动的核心是不断变动marker的坐标。

最终效果:

主要参考了  Mapbox实现动态轨迹_mapbox 轨迹_二五25的博客-CSDN博客

mapbox轨迹动画效果_mapbox动画_Chaoying.的博客-CSDN博客

但是我们这里的需求有变化。使用turf.along和turf.lineChunk出来的数据,只包含坐标点.

不包含其他信息。需要携带其他的信息就没有办法。比如起点或者终点在室内,那么就办法设置楼层。

所以这里要对数组做处理。

数据处理一:将后台返回的数据处理成我们想要的格式

我这里请求路线返回的数据长这样。可以看出返回的数据结构不符合turf.lineString的要求。


处理数据,将所有的需要的数据,室内楼层,偏转角度,每段路线的终点,每段路线之间的距离通通通过handleRouteData函数处理拿到。

 主要代码为:


        function handleRouteData(route) { // 处理数据 返回线数据以及所以点集合
            let pointCollects = []

            for (let i = 0; i < route.length; i++) {
                pointCollects.push({
                    "properties": {
                        "indoor": route[i].indoor,
                        "floor": route[i].startFloor
                    },
                    'geometry': route[i].geometry
                });
                let str = route[i].geometry.coordinates.join(',').split(',')
                str = str.map(j => Number(j))

                console.log("str", str)
                let totalPoint = []
                for (let i = 0; i < str.length; i++) {
                    if (i % 2 === 0) {
                        totalPoint.push([str[i], str[i + 1]])
                    }
                }

                let start = turf.point(totalPoint[0])
                let end = turf.point(totalPoint[totalPoint.length - 1])
                let bearing = turf.bearing(start, end)

                if (i === route.length - 1) {
                    lastPoint = totalPoint[totalPoint.length - 1]
                }
                console.log("totalPoint", totalPoint)

                splitLine.push(turf.lineString(totalPoint))
                splitDis.push(turf.length(splitLine[i], { units: 'meters' }));
                totalFloor.push(route[i].startFloor)
                totalBearing.push(bearing)
                totalIndoor.push(route[i].indoor)

            }

            return {
                pointCollects, // 线数据
                splitLine, // 每一段路线的线信息
                splitDis, // 每一段路线的距离
                totalFloor, // 每一段路线所在楼层数
                totalBearing, // 每一段路线的偏移角度
                totalIndoor,  // 每一段路线是否在室内
                lastPoint // 每一段路线的终点
            }
        }

数据处理二:将上一步处理好的数据,整合成数组。

主要代码是:

   function dealData(speed) {
            let anverageLine = []
            for (let i = 0; i < res.splitDis.length; i++) {
                let along = null
                if (res.totalIndoor[i]) {
                    // 如果这一度在室内 那么就多分几个点吧--因为层级的原因
                    along = turf.lineChunk(res.splitLine[i], (5 * speed) * 0.4, { units: 'meters' });
                } else {
                    along = turf.lineChunk(res.splitLine[i], 5 * speed, { units: 'meters' });
                }
                console.log(along);
                along.features.map(j => {
                    j.geometry.coordinates.map(k => {
                        anverageLine.push([k, res.totalIndoor[i], res.totalFloor[i], res.totalBearing[i]])
                    })
                })
                if (i === res.splitDis.length - 1) {
                    anverageLine.push([lastPoint, res.totalIndoor[i], res.totalFloor[i], res.totalBearing[i]])
                }
            }
            return anverageLine
        }

这里的思路是,根据距离将线切割成N个点,因为每次切割的点不包括这段路的终点。所以这里必须要手动加入路线终点。不然marker运动的时候,无法走到路程尽头。

这里的anverageLine就是我们需要marker移动所需要的所有的信息。

marker移动速度的快慢就是通过speed的大小决定,speed越大,就表明这一段路线分割成的点就越少。运动速度就越快

室内层级比室外层级更大,marker移动肉眼可见变得快一点,猜测是近大远小的原理吧。所以室内的点分的更多一点。至于慢多少可以由自己决定,这里是0.4.

最后开启动画,使用requestAnimationFrame,让marker动起来。

主要代码是

        var requestId;
        function loop(speed) {
            requestId = undefined;
            let anverageLine = dealData(speed);
            map.easeTo({
                center: anverageLine[step][0],
                zoom: 17,
                duration: 50,
            })
            if (anverageLine[step][1]) {
                map.setLevel(anverageLine[step][2])
                map.easeTo({
                    center: anverageLine[step][0],
                    zoom: 19,
                })
            }
            step = step + 1;
  
            if (step === anverageLine.length - 1) {
                requestId = undefined;
                step = 0
                return
            }
            go(speed);
            marker.setLngLat(anverageLine[step][0])

        }

        function go(speed) {

            if (!requestId) {
                requestId = window.requestAnimationFrame(() => loop(1));
            }
        }

至此 大功告成

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个使用MapboxGL添加一个marker并实现高亮闪烁效果的完整代码示例: ```html <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>MapboxGL Marker Highlight Animation</title> <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" /> <script src="https://api.mapbox.com/mapbox-gl-js/v2.5.1/mapbox-gl.js"></script> <link href="https://api.mapbox.com/mapbox-gl-js/v2.5.1/mapbox-gl.css" rel="stylesheet" /> <style> body { margin: 0; padding: 0; } #map { position: absolute; top: 0; bottom: 0; width: 100%; } .highlight-animation { animation: highlight 1s infinite; } @keyframes highlight { 0% { opacity: 1; transform: scale(1); } 50% { opacity: 0.5; transform: scale(1.5); } 100% { opacity: 1; transform: scale(1); } } </style> </head> <body> <div id="map"></div> <script> mapboxgl.accessToken = 'YOUR_MAPBOX_ACCESS_TOKEN'; var lng = -122.4194; // 经度 var lat = 37.7749; // 纬度 var zoomLevel = 12; // 缩放级别 // 创建地图实例 var map = new mapboxgl.Map({ container: 'map', style: 'mapbox://styles/mapbox/streets-v11', center: [lng, lat], zoom: zoomLevel }); // 创建一个图层,并向地图添加一个marker var marker = new mapboxgl.Marker({ element: createMarkerElement() }) .setLngLat([lng, lat]) .addTo(map); // 为标记元素添加动画marker.getElement().classList.add('highlight-animation'); // 创建标记元素及样式 function createMarkerElement() { var el = document.createElement('div'); el.className = 'marker'; el.style.backgroundImage = 'url(https://example.com/your-marker-icon.png)'; // 替换为您自己的标记图标URL el.style.width = '40px'; el.style.height = '40px'; el.style.backgroundRepeat = 'no-repeat'; el.style.backgroundSize = 'cover'; return el; } </script> </body> </html> ``` 请确保将YOUR_MAPBOX_ACCESS_TOKEN替换为您自己的Mapbox访问令牌,并将`https://example.com/your-marker-icon.png`替换为您自己的标记图标的URL。 通过上述代码,您将能够在MapboxGL地图上添加一个marker,并为其添加高亮闪烁的动画效果。根据您的需求,您可以调整地图的样式、标记的位置和动画效果
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值