mapbox组件应用

7 篇文章 0 订阅
1 篇文章 0 订阅


一、切换菜单、地图尺寸刷新

<ngx-map #map [mapUrl]="mapUrl" [showNavigation]="false" [isTransform]="true" [showLOC]="true"
 (onMapLoad)="mapload()" (onMapStyleChanged)="onMapStyleChanged()">
</ngx-map>
setMapChange() {
    this.onMapload = false;
    this.mapUrl = this.area == 'SH' ? `${this.map_url}/styles/shanghai_city_albers/style.json` : `${this.map_url}/styles/csj_province_albers/style.json`;
    this.mapbox.changeStyle(this.mapUrl);
  }

  onMapStyleChanged() {
    this.mapload();
  }

二、清除图层

clearLayer() {
    //先移除layer 后移除source
    if (this.mapbox && this.mapbox.getLayer('pngProduct')) {
      this.mapbox.removeLayer('pngProduct');
    }
    if (this.mapbox && this.mapbox.getSource('pngProduct')) {
      this.mapbox.removeImage('pngProduct');
    }
  }

三、 地图添加站点数据


//先 addSource  后addLayer
 let geojson = {
      "type": "FeatureCollection",
      "features": []
    }

this.mapbox.addSource('point', {
      'type': 'geojson',
      'data': geojson
    });
await this.mapbox.addLayer({
      'id': 'point',
      'type': 'circle',
      'source': 'point',
      "paint": {
        'circle-radius': 3,
        "circle-color": {
          "type": "interval",
          "property": "data",
          "stops": this.stops,
        }
      }
    }, "anno");

四、 拼接geojson数据

   createGeoJSONCircle(lngLat: { lat: number, lng: number }, radiusInKm: number, steps = 64) {
        let geojson = {
            "type": "FeatureCollection",
            "features": [{
                "type": "Feature",
                "geometry": {
                    "type": "Polygon",
                    "coordinates": []
                }
            }]
        }

        let ret = [];
        let distanceX = radiusInKm / (111.320 * Math.cos(lngLat.lat * Math.PI / 180));
        let distanceY = radiusInKm / 110.574;

        let theta, x, y;
        for (let i = 0; i < steps; i++) {
            theta = (i / steps) * (2 * Math.PI);
            x = distanceX * Math.cos(theta);
            y = distanceY * Math.sin(theta);
            let lng = lngLat.lng + x;
            let lat = lngLat.lat + y

            ret.push([lng, lat]);

            // var pt = turf.point([lng, lat]);
            // var converted = turf.toMercator(pt);
            // console.log([lng, lat]);
            // console.log(pt);
            // console.log(converted);
            // console.log("=========================================================");
        }
        ret.push(ret[0]);

        geojson.features[0].geometry.coordinates = [ret];

        return geojson;
    }

五、添加站点信息

点击地图,弹框展示站点信息(实例1)

//弹框popUP 站点详细信息
  onClickStation() {
    //点击站点 展示站点信息
    this.mapbox.onLayerClick("station", (e) => {
      let props: PestStat = e.features[0].properties;
      if (!props) return;
      //查站号 站点 省名
      let statData: Station = this.stations.find(stat => stat.v01000 == props.v01000)
      this.propsHTML =
        `<p style="padding-left:10px">` + statData.cAera + statData.cPrvoName + "省" + statData.cCity + `</p>
        <div class="station-tbale">
             <div class="col-sm-8 station_title">灾害名称</div>
             <div class="col-sm-14">`+ props.disastername + `</div>
         </div>
        <div class="station-tbale" >
             <div class="col-sm-8 station_title">区站号</div>
             <div class="col-sm-8">`+ props.v01000 + `</div>
             <div class="col-sm-8 station_title">区站名</div>
             <div class="col-sm-8">`+ statData.cStatName + `</div>
        </div>
        <div class="station-tbale">
             <div class="col-sm-8 station_title">指数</div>
             <div class="col-sm-8">`+ props.disaindex + `</div>
             <div class="col-sm-8 station_title">指数等级</div>
             <div class="col-sm-8">`+ props.grade + `</div>
        </div>
        <div class="station-tbale">
             <div class="col-sm-8 station_title">年份</div>
             <div class="col-sm-8">`+ props.v04001 + "年" + `</div>
             <div class="col-sm-8 station_title">连续日数</div>
             <div class="col-sm-8">`+ props.condays + `</div>
        </div>
        <div class="station-tbale">
             <div class="col-sm-8 station_title">作物类别</div>
             <div class="col-sm-8">`+ props.disastercrop + `</div>
             <div class="col-sm-8 station_title">模型版本号</div>
             <div class="col-sm-8">`+ props.vVersion + `</div>
        </div>
        <div class="station-tbale">
             <div class="col-sm-8 station_title">起始时间</div>
             <div class="col-sm-8">`+ (props.sdate).toString().substring(0, 4) + "年" + Number((props.sdate).toString().substring(4, 6)) + "月" + Number((props.sdate).toString().substring(6, 8)) + "日" + `</div>
             <div class="col-sm-8 station_title">终止时间</div>
             <div class="col-sm-8">`+ (props.edate).toString().substring(0, 4) + "年" + Number((props.edate).toString().substring(4, 6)) + "月" + Number((props.edate).toString().substring(6, 8)) + "日" + `</div>
        </div>`;
      this.popup = new Popup()
        .setLngLat(e.eventData.lngLat)
        .setHTML(this.propsHTML)
        .addTo(this.mapbox.map);
    })
  }
  
async initStat() {
    this.title = `${this.dateArr.sYear}年~${this.dateArr.eYear}${this.area.cName}${this.task.title}`;
    let dayCount = ((new Date(this.dateArr.eYear, this.dateArr.eMonth, 1).getTime() - new Date(this.dateArr.eYear, this.dateArr.eMonth - 1, 1).getTime()) / 24 / 3600 / 1000).toString().padStart(2, "0");
    let eDate = this.dateArr.eYear + this.dateArr.eMonth.toString().padStart(2, "0") + dayCount + "000000"
    let sDate = this.dateArr.sYear + this.dateArr.sMonth.toString().padStart(2, "0") + "01000000"
    let prn = this.productService.makeProductName("BABJ", "WCRMECO", eDate, sDate, this.task.style_name, "1KM", this.area.cCoverage, "geojson")
    let geojson
    let isGeojson: boolean = false
    await this.productService.getContent(prn).toPromise().then(data => {
      if (!data.features) {
        this.message.error("无" + this.title + "站点数据")
        return
      }
      isGeojson = true;
      geojson = data
    }).catch(error => {
      this.message.error(this.title + "站点数据获取失败")
    })
    if (!isGeojson) {
      return
    }
    await this.mapbox.addSource('point', {
      'type': 'geojson',
      'data': geojson
    });
    // console.log(geojson);

    // let geojson = "Z_AGME_C_BABJ_201912000000_P_CAGMSS_WCRMECO_SCOP-RRR-RELE-NPP-200001000000_1KM_CHN_L88_PD_000_00.geojson"
    // this.mapbox.addSource('point', {
    //   'type': 'geojson',
    //   'data': this.productService.downloadUrl(geojson)
    // });
    await this.mapbox.addLayer({
      'id': 'point',
      'type': 'circle',
      'source': 'point',
      "paint": {
        'circle-radius': 3,
        "circle-color": {
          "type": "interval",
          "property": "data",
          "stops": this.stops,
        }
      }
    }, "anno");

  }
//移除popup
 if (this.popup) {
      this.popup.remove();
      var popUps = document.getElementsByClassName("mapboxgl-popup");
      if (popUps[0]) {
        popUps[0].remove();//关闭弹框
        console.log('popup.remove');
      }
  }

点击地图的站点,弹框显示站点信息(实例2)

 <ngx-map #map [mapUrl]="mapUrl" [showNavigation]="false" [isTransform]="isAlbers" [showLOC]="true"
        [showDraw]="true"   (onMapLoad)="mapload()" (onMapStyleChanged)="onMapStyleChanged()">
 </ngx-map>
 mapload() {
    this.mapLoaded = true;
    this.mapbox.map.setMinZoom(3.5);
    // this.mapbox.map.setMaxBounds(new LngLatBounds({ lng: 57.727166775683266, lat: 13.289328964438425 }, { lng: 150.50542144278765, lat: 49.732028771519175 }));
    // this.mapbox.map.setMaxBounds(new LngLatBounds({ lng: 50, lat: 0 }, { lng: 150, lat: 50 }));
    this.mapDefaultService.init(this.mapbox);
    // 点击获取县的经纬度以及名称
    this.mapbox.onLayerClick(this.mapDefaultService.LayerId.COUNTY, (event: LayerEventData) => {
      this.areaName[2] = event.features[0].properties["NAME"]
    });
    // 点击获取市的经纬度以及名称
    this.mapbox.onLayerClick(this.mapDefaultService.LayerId.CITY, (event: LayerEventData) => {
      this.areaName[1] = event.features[0].properties["NAME"]
    });
    // 点击获取省的经纬度以及名称
    this.mapbox.onLayerClick(this.mapDefaultService.LayerId.PROVINCE, (event: LayerEventData) => {
      this.areaName[0] = event.features[0].properties["NAME"]
    });
    //点击站点 展示站点信息
    this.mapbox.onLayerClick("point", (e) => {
      this.stations = JSON.parse(localStorage.getItem("stations"))
      let props = e.features[0].properties;
      // console.log(props);
      if (!props) return;
      //查站号 站点 省名
      let statData = this.stations.filter(stat => stat.v01000 == props.id)
      //翻译图例
      let legend = JSON.parse(JSON.stringify(this.stops.find(item => item[0] == props.data)))
      this.legend.items.forEach((value, key) => {
        if (value == legend[1]) {
          legend[0] = key;
        }
      })
      this.propsHTML =
        `<p style="padding-left:10px">` + statData[0].cPrvoName + statData[0].cAera + statData[0].cCity + `</p>
        <div class="row station-tbale" style="width:250px">
             <div class="col-sm-8 station_title">省份</div>
             <div class="col-sm-8">`+ statData[0].cPrvoName + `</div>
             <div class="col-sm-8 station_title">站名</div>
             <div class="col-sm-8">`+ statData[0].cStatName + `</div>
        </div>
        <div class="row station-tbale" style="width:250px">
             <div class="col-sm-8 station_title">站号</div>
             <div class="col-sm-8">`+ statData[0].v01000 + `</div>
             <div class="col-sm-8 station_title">R值</div>
             <div class="col-sm-8">`+ Number(props.R).toFixed(3) + `</div>
        </div>
        <div class="row station-tbale" style="width:250px">
             <div class="col-sm-8 station_title">站点数据</div>
             <div class="col-sm-14">`+ legend[0] + `</div>
        </div>
        <div class="row station-tbale" style="width:250px">
             <div class="col-sm-8 station_title">相关类型</div>
             <div class="col-sm-14">`+ this.task.title + `</div>
        </div>`;
      this.popup = new Popup()
        .setLngLat(e.eventData.lngLat)
        .setHTML(this.propsHTML)
        .addTo(this.mapbox.map);
    })
  }

六、 stop的四种类型

//1.指数类型,最终输出值由stops中的差值项进行区间范围内的指数级差值计算生成
map.addLayer({
     "paint": {
         "circle-color": {
           // 指数类型type可不写
         "type": "exponential",
         "property": "val",
         "stops": [
               // properties.val为0,圆的颜色为红色
               [0, "red"],
              // properties.val为500,圆的颜色为绿色
               [500, "green"],
               // properties.val为1000,圆的颜色为蓝色
               [1000, "blue"]
           ],
           // 可选,默认值:1。插值运算的曲率指数基数,控制最终计算结果值的增长率,值越大,最终计算结果值越大,当值趋近于1时,函数采用线性计算方式。
           "base": 0.9
       }
   }
});
//2.区间类型 最终输出值由stops中的差值项进行区间范围内的阶梯型差值计算生成,stops中的输入参数必须为数值类型。
map.addLayer({
     "paint": {
         "circle-opacity": {
             "type": "interval",
             "property": "val", // 不写,将会根据zoom设置
             "stops": [
                 // properties.val大于等于0时,圆颜色为红色
                 [0, "red"],
                 // properties.val大于等于500时,圆颜色为绿色
                 [500, "green"],
                 // properties.val大于等于1000时,圆颜色为蓝色
                 [1000, "blue"],
             ]
         }
     }
});
//3.种别类型:最终输出值完全匹配stops中的输入值对应的输出值
map.addLayer({
     "paint": {
         "fill-color": {
         "type": "categorical",
         "property": "num", // 必写
         "stops": [
               // 仅当properties.num等于5时,面颜色为红色
               [5, "red"],
               // 仅当properties.num等于10时,面颜色为绿色
               [10, "green"],
           ]
       }
   }
});
//4.恒等类型 最终输出值完全等于输入值
map.addLayer({
 "paint": {
     "line-color": {
         "type": "identity",
           // 线颜色直接取properties.color的值
         "property": "color"
       }
   }
});

按数据的最小最大值范围渲染颜色,生成图例(实例)

  private loadYield(id: string, item: any) {
    let yieldSource = this.map.getSource(id);
    let showLayer = this.map.getLayer(id);
    if (!yieldSource || !showLayer) return;
    this._todoService.getProvYieldPolygon(this.selYear, item.text).then(areaData => {
      if (!areaData) {
        yieldSource.setData({
          "type": "FeatureCollection",
          "features": []
        });
        // this.map.removeLayer(this.yieldResId);
        // this.map.removeSource(this.yieldResId);
        if (this.activeLayer == id)
          this.yzNgxToastyService.warning("提示", "【" + this.selectedItem.text + "】作物" + this.selYear + "年无产量信息", 2000);
        return;
      }
      yieldSource.setData(areaData);
      let filterPro = "产量(吨)";
      // 排序
      areaData.features.sort((val1, val2) => {
        let proVal1 = val1['properties'][filterPro];
        let proVal2 = val2['properties'][filterPro];

        if (proVal1 < proVal2) {
          return -1;
        } else if (proVal1 > proVal2) {
          return 1;
        } else {
          return 0;
        }
      });

      // 渲染值范围
      let minValue = Math.floor(areaData.features[0]['properties'][filterPro]);

      let maxValue = minValue;
      for (let i = areaData.features.length - 1; i >= 0; i--) {
        let t = Math.ceil(areaData.features[i]['properties'][filterPro]);
        if (t && t > 0) {
          maxValue = t;
          break;
        }
      }
      let midValue =Number(((maxValue + minValue) / 2).toFixed(1));
      let stops = [
        [minValue, "#51bbd6"],
        [midValue, "#f1f075"],
        [maxValue, "#f28cb1"]
      ];

      let items = new Map<string, string>();

      for (let i = 0; i < stops.length; i++) {
        if (stops[i] == stops[stops.length - 1]) {
          items.set("大于" + String(stops[i][0]), String(stops[i][1]));
        } else {
          items.set(String(stops[i][0] + "~" + stops[i + 1][0]), String(stops[i][1]));
        }
      }
      this.legend = new Legend();
      this.legend.unit = '产量(吨)'
      this.legend.items = items;
      this.map.addLegendControl(this.legend, "bottom-left");
      if (this.legendShow) {
        document.getElementsByClassName("legend")[0].className = "show legend";
      } else {
        document.getElementsByClassName("legend")[0].className = "hidden legend";
      }
      this.map.setFilter(id, ["has", filterPro]);
      this.map.setPaintProperty(id, "fill-color", {
        "property": filterPro,
        "stops": stops,
        "type": "interval",//区间类型 最终输出值由stops中的差值项进行区间范围内的阶梯型差值计算生成,stops中的输入参数必须为数值类型。
      });
      this.map.setPaintProperty(id, "fill-opacity", 0.8);
      if (this.activeLayer == id) {
        this.map.setVisibility(id, true);
      }
      else {
        this.map.setVisibility(id, false);
      }
    });
  }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值