mapbox实现加载多条航线,以及点击某条航线实现飞行效果

代码在VUE中实现,使用ts语法,某些值是state中的值,自行甄别

航线为以某一机场为中心点,随机取20点目地点得到

  function createAirline(){
        // 随机取出航线中的任意条航线(用于测试)
        function RandomNumBoth(arr:any[], maxNum) {
          const numArr = [];
          const arrLength = arr.length;
          for (let i = 0; i < arrLength; i++) {
            //取出随机数 
            const number = Math.floor(Math.random() * arr.length); //生成随机数num
            numArr.push(arr[number]); //往新建的数组里面传入数值
            arr.splice(number, 1); //传入一个删除一个,避免重复
            if (arr.length <= arrLength - maxNum) {
              return numArr;
            }
          }
          console.log(1111);
                
        }

        const origin = data.geoCenter;
        const  destination = RandomNumBoth(data.airportList_.geo,20)
        console.log(destination[0],'机场经纬度');

        for(let i=0;i<destination.length;i++){

          let a ={
                'id': "route",
                'type': 'FeatureCollection',
                'features': [
                    {
                        'type': 'Feature',
                        'geometry': {
                            'type': 'LineString',
                            'coordinates': [origin, destination[i]]
                        }
                    }
                ]
              }  

            map.value?.addSource('route'+i, {
                'type': 'geojson',
                'data': a
            });
            map.value?.addLayer({
                'id': 'route'+i,
                'source': 'route'+i,
                'type': 'line',
                'layout': {
                    "line-join": "round",
                    "line-cap": "round",
                },
                'paint': {
                    'line-width':3,
                    // 'line-blur': 3,
                    'line-opacity': 0.6,
                  
                    'line-color': 'red'
                }
            });   



            const point = {
              'type': 'FeatureCollection',
              'features': [
                  {
                      'type': 'Feature',
                      'properties': {},
                      'geometry': {
                          'type': 'Point',
                          'coordinates': origin
                      }
                  }
              ]
            };

            


 
        let counter = 0;

        map.value?.on("click","route"+i,function(){

            map.value?.addSource('point'+i, {
                'type': 'geojson',
                'data': point
            });

            map.value?.addLayer({
                'id': 'point'+i,
                'source': 'point'+i,
                'type': 'symbol',
                'layout': {
                    'icon-image': 'airport-15',
                    'icon-size': 2,
                    'icon-rotate': ['get', 'bearing'],
                    'icon-rotation-alignment': 'map',
                    'icon-allow-overlap': false,
                    'icon-ignore-placement': true
                },
                "paint": {
                    "icon-color" : "#FF0000"
                }
            });

            const lineDistance = turf.lineDistance(a.features[0], 'kilometers');
            const stepArr = [];
            const steps = 500; // 步数(帧) 
            for (let i = 1; i < lineDistance; i += lineDistance / steps) {
              const lnglat = turf.along(a.features[0], i, 'kilometers');
              stepArr.push(lnglat.geometry.coordinates);
            }
            
            a.features[0].geometry.coordinates = stepArr ;

          

            function animate() {
              // Update point geometry to a new position based on counter denoting
              // the index to access the arc.
              point.features[0].geometry.coordinates =
                  a.features[0].geometry.coordinates[counter];

              // Calculate the bearing to ensure the icon is rotated to match the route arc
              // The bearing is calculate between the current point and the next point, except
              // at the end of the arc use the previous point and the current point
              point.features[0].properties.bearing = turf.bearing(
                  turf.point(
                      a.features[0].geometry.coordinates[
                          counter >= steps ? counter - 1 : counter
                      ]
                  ),
                  turf.point(
                      a.features[0].geometry.coordinates[
                          counter >= steps ? counter : counter + 1
                      ]
                  )
              );

              // Update the source with this new data.
              map.value?.getSource('point'+i).setData(point);

              // Request the next frame of animation so long the end has not been reached.
              if (counter < steps) {
                  requestAnimationFrame(animate);
              }

              counter = counter + 1;
              console.log("成功没");
              
          }
            animate();
        })



        }


      }
posted @   青川薄  阅读(557)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
点击右上角即可分享
微信分享提示