当前位置: 首页 > 工具软件 > Layer Styles > 使用案例 >

VectorTileLayer更换style

法玮
2023-12-01

问题描述:

底图(矢量切片图层的url)不变,但是需要添加上不同的style形成动画轮播的效果。
给图层更换样式不难,找到对应的feature,使用feature.setStyle就可以了。但是我在项目中遇到的问题是获取不到feature,或者获取到的feature不可用(我一同事就遇到了使用feature.setStyle不生效的情况,最后也没有找到原因,最后每次更换样式时添加不同样式的图层,然后添加了一堆的layers,导致地图非常庞大)。
这篇文章就是讲的就是没有feature的时候如何更换样式——layer.setStyle

代码详解:

// prop: 用来拼接url的
// layerId: 图层id,唯一标识
// geom:用来更改不同style
loadRainForcastLayer(prop, layerId,geom) {
    let levelJson = JSON.parse(geom);
    // style 和 setStyle 方法中会出现this指向不同问题,所以先提出来
    let that = this
	//在地图中找到所有的layer,判断要添加的图层是否已存在
    this.getLayers().forEach((layer) => {
      if (layer.getProperties().id&&layer.getProperties().id == layerId) {
        this.rainForcastLayer = layer;
      }
    });
    //如果图层存在,直接更改样式 
    if (this.rainForcastLayer) {
		this.rainForcastLayer.setVisible(true);
        this.rainForcastLayer.setStyle(function(feature,res){
          let id = feature.get("id");
          
          // 从这里往下 通过id获取铺图层的样式 颜色  ↓
          let number=levelJson[id]?levelJson[id]:0
          let level=that.getLevel(number)
         	
          let text=String(number)==0?"":String(number)
          let color=conf.mapViewer.Predicforeca[level]
    	// 从这里往上 通过id获取铺图层的样式 颜色  ↑
    	
          let vectorTileStyle = new Style({
            stroke: new Stroke({
              color: "rgba(255,255,255,0)",
              width: 2,
            }),
            fill: new Fill({
              color: color
            }),
            text: new Text({ //文本样式
              font: '12px Calibri,sans-serif',
              fill: new Fill({
                color: '#000'
              }),
              stroke: new Stroke({
                color: '#000',
                width: 1,
              }),
             // 注意这个text只能是 string 格式,所以前面进行了转换
              text:text
            }),    
            
          });
          return vectorTileStyle
        })
			return;
		}


		let style = "";
		
		//这里开始拼接url,如果有完整的可用的url可以不看这一段  ↓
		var gridsetName = "EPSG:4326";
    	var gridNames = [
			"EPSG:4326:0",
			"EPSG:4326:1",
			"EPSG:4326:2",
			"EPSG:4326:3",
			"EPSG:4326:4",
			"EPSG:4326:5",
			"EPSG:4326:6",
			"EPSG:4326:7",
			"EPSG:4326:8",
			"EPSG:4326:9",
			"EPSG:4326:10",
			"EPSG:4326:11",
			"EPSG:4326:12",
			"EPSG:4326:13",
			"EPSG:4326:14",
			"EPSG:4326:15",
			"EPSG:4326:16",
			"EPSG:4326:17",
			"EPSG:4326:18",
		];
    let format = "application/vnd.mapbox-vector-tile";
    var resolutions = [0.703125, 0.3515625, 0.17578125, 0.087890625, 0.0439453125, 0.02197265625, 0.010986328125, 0.0054931640625, 0.00274658203125, 0.001373291015625, 6.866455078125E-4, 3.4332275390625E-4, 1.71661376953125E-4, 8.58306884765625E-5, 4.291534423828125E-5, 2.1457672119140625E-5, 1.0728836059570312E-5, 5.364418029785156E-6, 2.682209014892578E-6, 1.341104507446289E-6, 6.705522537231445E-7, 3.3527612686157227E-7];
    let vectorTileParams = {
			REQUEST: "GetTile",
			SERVICE: "WMTS",
			VERSION: "1.0.0",
			LAYER: prop.layer,
			STYLE: style,
			TILEMATRIX: gridsetName + ":{z}",
			TILEMATRIXSET: gridsetName,
			FORMAT: format,
			TILECOL: "{x}",
			TILEROW: "{y}",
		};
    var projection = new Projection({
			code: "EPSG:4326",
			units: "degrees",
			axisOrientation: "neu",
		});

    let baseUrl = ipConfig.geoServer + "/gwc/service/wmts";
		let url = baseUrl + "?";
		for (var param in vectorTileParams) {
			url = url + param + "=" + vectorTileParams[param] + "&";
		}
    //这里结束拼接url,如果有完整的可用的url可以不看这一段  ↑
    
    //第一次添加该图层
    this.rainForcastLayer = new VectorTileLayer({
      style: function(feature){
        let id = feature.get("id");
        let number=levelJson[id]?levelJson[id]:0;
        let level=that.getLevel(number)
        let text=String(number)==0?"":String(number)
        let color=conf.mapViewer.Predicforeca[level]
        let styles=new Style({
          stroke: new Stroke({
            color: "rgba(255,255,255,0)",
            width: 2,
          }),
          fill: new Fill({
            color: color
          }),
          text: new Text({ //文本样式
            font: '12px Calibri,sans-serif',
            stroke: new Stroke({
              color: '#000',
              width: 1,
            }),
            fill: new Fill({
              color: '#000'
            }),
            text:text
          })
        })
        return styles;
      },
      zIndex: ZINDEXCONSTANT.NINECLASSLAYER,
      id: layerId,
      projection: projection,
      maxResolution: 350,
      source: new VectorTileSource({
        projection: projection,
        tileGrid: new WMTSTileGrid({
          tileSize: [256, 256],
          origin: [-180.0, 90.0],
          resolutions: resolutions,
          matrixIds: gridNames,
        }),
        format: new MVT(),
        url: url,
        wrapX: true,
        tilePixelRatio: 1,
        
      }),
    });
	this.addLayer(this.rainForcastLayer);


  }

对地图操作的方法写好了,然后动画的时候直接设置一个定时器就可以了:

play(){
  this.timeInterval = setInterval(() => {
            if (this.currentRowIndex < this.forecastList.length - 1) {
              this.currentRowIndex++;
            } else {
              this.currentRowIndex = 0;
            }
            this.levelJson=JSON.parse(this.forecastList[this.currentRowIndex].predicProduct)
            this.loadRainForcastLayer(
               {
                  key: 'layer-rainForcast',
                  layer:"meteo_qpf:QPF",
                  title: '降雨预报',
                },
                "layer-rainForcast",
                this.forecastList[this.currentRowIndex].predicProduct
              );
          }, 3000);}

然后在停止的时候:

stop(){
	//将对应图层隐藏
  this.rainForcastLayer && this.rainForcastLayer.setVisible(false);
  //清除定时器
  clearInterval(this.timeInterval)
}

然后功能就可以完成了!

 类似资料: