基于mineMap的地图台风灾害预警轨迹可视化方案

1.需求概要
可视化界面显示气象云图及台风中心运动变化,实时数据显示;
2.效果预览
在这里插入图片描述
方案实施
1.>图层构成分析:
可视范围内构成的应该包含基础图层和动态移动图层,运动线路,运动风标,及运动信息框;
2.>结构拆分:
//:基于单图层创建多个根据风力大小为半径的风面圆图层;
数据组装:

      /**
       * @Description:圆心处理

       * @Author: ShiWei

       * @Date: 2020-09-07
       */
      makeWindGeo(fea,i) {
        const cen = turf.point(fea[i].geometry.coordinates)
        // 圆形展示
        return turf.sector(cen, fea[i].properties.r10, 0, 360)
      },
      
  if( winData.length!==0){
          let dataObj=winData.data;
           let r7=Math.floor(Math.random() * 200 + 20);
           let r10= Math.floor(Math.random() * 300 + 50);
            dataObj.map((item,index) =>{
            let properties={wl:parseFloat(item.mws),r10:r10,r7:r7,startTime:item.startTime,
              endTime:item.endTime,
              centerPres:item.centerPres,
              mws:item.mws,
              mwsMax:item.mws};
            let point=[];
            //单点信息
            point.push(parseFloat(item.lon),parseFloat(item.lat))
            stp.push(this.mapController.makeFeature("Point",point,properties))
            features.push(this.makeWindGeo(stp,index))
          })
          let source = this.mapController.makeFeatureCollection(features)
          this.mapController.addSource(this.map, "circle-source-1", source)
          this.drwWinCircle('win-circle','circle-source-1',this.map)
      /**
       * @Description: 绘制圆形风力面 采用单图层绘制多个同类面

       * @Author: ShiWei

       * @Date: 2020-09-07
       */
      drwWinCircle(id,source,map){
        if (map.getLayer(id)) {
          map.removeLayer(id)
        }
        map.addLayer({
          "id": id,
          "type": "fill",
          "source": source,
          "paint": {
            "fill-color": "#35e2ce",
            "fill-opacity": 0.2,
          }
        });
      },

2.同操作拆分出风面中心点point,及轨迹线路

      if( winData.length!==0){
          let dataObj=winData.data;
           let r7=Math.floor(Math.random() * 200 + 20);
           let r10= Math.floor(Math.random() * 300 + 50);
            dataObj.map((item,index) =>{
            let properties={wl:parseFloat(item.mws),r10:r10,r7:r7,startTime:item.startTime,
              endTime:item.endTime,
              centerPres:item.centerPres,
              mws:item.mws,
              mwsMax:item.mws};
            let point=[];
            //单点信息
            point.push(parseFloat(item.lon),parseFloat(item.lat))
            //风力轨迹坐标
            line.push(point);
            stp.push(this.mapController.makeFeature("Point",point,properties))
            infos.push({point:point,properties})
            //中心点
            winCenter.push(this.mapController.makeFeature("Point",point,properties))
            features.push(this.makeWindGeo(stp,index))
          })
          features.map((ite,idx)=>{
            markerList.push(ite.geometry.coordinates[0][0])
          })
          let source = this.mapController.makeFeatureCollection(features)
          let winCenterSource = this.mapController.makeFeatureCollection(winCenter)
          this.mapController.addSource(this.map, "center-source-1", winCenterSource)
          this.drwWinCenter('win-center','center-source-1',this.map)
          let geo = {
            type: "FeatureCollection",
            features: [{
              type: "Feature",
              geometry: {"type": "LineString", "coordinates": line},
              properties: {}
            }]
          }
          //运动数装倒序组装
          this.infoList=infos.reverse();
          this.mapController.addSource(this.map, "line-source-1", geo);
          this.drwWinLine('line-win',"line-source-1",this.map)
          this.addMarker(this.map,line)
          this.moveList=line.reverse();
          minemaputil.fitBounds(this.map, source, { padding: 200 });
          }

3.绘制中心点及轨迹路线

  /**
       * @Description:风圈中心位置标识

       * @Author: ShiWei

       * @Date: 2020-09-08
       */
      drwWinCenter(id,source,map){
        if (map.getLayer(id)) {
          map.removeLayer(id)
        }
        map.addLayer({
          "id": id,
          "type": "circle",
          "source": source,
          "paint": {
            "circle-color": {
              "property": "wl",
              "stops": [
                [0, "rgba(255,255,255,0.60)"],
                [1, "rgba(230,230,230,0.60)"],
                [2, "rgba(204,204,204,0.60)"],
                [3, "rgba(179,179,179,0.60)"],
                [4, "rgba(154,154,154,0.60)"],
                [5, "rgba(62,217,230,0.60)"],
                [6, "rgba(79,214,203,0.60)"],
                [7, "rgba(85,207,137,0.60)"],
                [8, "rgba(109,214,106,0.60)"],
                [9, "rgba(160,230,69,0.60)"],
                [10, "rgba(213,230,69,0.60)"],
                [11, "rgba(255,232,79,0.60)"],
                [12, "rgba(245,188,56,0.60)"],
                [13, "rgba(245,144,56,0.60)"],
                [14, "rgba(235,103,47,0.60)"],
                [15, "rgba(218,73,43,0.60)"],
                [16, "rgba(190,46,45,0.60)"],
                [17, "rgba(129,56,184,0.60)"],
                [18, "rgba(67,2,116,0.60)"]
              ]
            },
            "circle-radius": 10
          }
        });
      },
      /**
       * @Description:绘制风力轨迹线路

       * @Author: ShiWei

       * @Date: 2020-09-08
       */
      drwWinLine(id,source,map){
        map.addLayer({
          "id": id,
          "type": "line",
          "source": source,
          "layout": {
            "line-join": "round",
            "line-cap": "round"
          },
          "paint": {
            "line-color": "#64a7c2",
            "line-width": 2,
            "line-opacity": 0.6
          }
        });
      },

4.风标

/**
       * @Description:风圈引导标记

       * @Author: ShiWei

       * @Date: 2020-09-08
       */
      addMarker(map,data){
          if(this.markerLister) {
            this.markerLister.remove();
          }
          let el = document.createElement('div');
          el.style.zIndex = 120;
          el.className = 'pin-wheel-marker';
          let p = document.createElement('div');
          p.className = 'pin-wheel-inner';
          el.appendChild(p);
          this.markerLister= new minemap.Marker(el, {offset: [-17, -17]}).setLngLat(data[data.length-1]).addTo(map);
          this.addInfoMarker(0)
      },

5.动态信息窗

 /**
       * @Description:动态信息窗体

       * @Author: ShiWei

       * @Date: 2020-09-08
       */

       addInfoMarker(i){
         let data=this.infoList;
        if(this.infoMarker) {
          this.infoMarker.remove();
        }
        let el=document.createElement('div');
            el.className="info-content";
        let line=document.createElement('li')
            line.className='info-line'
        el.appendChild(line)
        let infoM=document.createElement('div');
            infoM.className='info-cls'
        let info=document.createElement('div');
            info.className='info-menu'
        let tt = document.createElement('li');
            tt.innerHTML='持续时间'+data[i].properties.startTime+'--'+data[i].properties.startTime;
            info.appendChild(tt);
        let qy=document.createElement('li');
            qy.innerHTML='中心气压'+data[i].properties.centerPres+'百帕';
            info.appendChild(qy);
        let fsMin =document.createElement('li');
            fsMin.innerHTML='最小风速'+data[i].properties.mws+'米/秒';
            info.appendChild(fsMin);
        infoM.appendChild(info)
        el.appendChild(infoM)
        this.infoMarker= new minemap.Marker(el, {offset: [8, -60]}).setLngLat(data[i].point).addTo(this.map);
       },

实时播放,暂停,重置

/**
       * @Description:播放风力轨迹

       * @Author: ShiWei

       * @Date: 2020-09-08
       */
      winStart(){
       if(this.moveList.length>0){
         let count=0;
         if(this.tep!==""){
           count=this.tep;
         }else {
           count=0;
         }
         this.moveTimer=setInterval(()=>{
           this.markerLister.setLngLat(this.moveList[count])
           this.addInfoMarker(count)
           this.tep=count;
           count++;
           if(count===this.moveList.length){
             clearInterval(this.moveTimer);
             this.moveTimer=null;
             this.markerLister.setLngLat(this.moveList[0])
             this.addInfoMarker(0)
           }
         },2000)
       }
      },
      /**
       * @Description:暂停

       * @Author: ShiWei

       * @Date: 2020-09-08
       */
      winStop(){
        if( this.moveTimer){
          clearInterval(this.moveTimer);
          this.moveTimer=null;
        }
        this.moveTimer=setInterval(()=>{
          let count=this.tep;
          this.markerLister.setLngLat(this.moveList[count])
          this.addInfoMarker(count)
          this.tep=count;
          count++;
          if(count===this.moveList.length){
            clearInterval(this.moveTimer);
            this.moveTimer=null;
            this.markerLister.setLngLat(this.moveList[0])
            this.addInfoMarker(0)
          }
        },2000)
      },
      /**
       * @Description:重置

       * @Author: ShiWei

       * @Date: 2020-09-08
       */
      rest(){
        this.tep="";
        clearInterval(this.moveTimer);
        this.moveTimer=null;
        this.markerLister.setLngLat(this.moveList[0])
        this.addInfoMarker(0)
      },

注意:利用turf将坐标转换成多边形;利用reverse()将数据顺序倒序达到预期效果
1 const cen = turf.point(fea[i].geometry.coordinates) // 圆形展示 return turf.sector(cen, fea[i].properties.r10, 0, 360) 2. reverse()

在这里插入图片描述