首页 > 其他分享 >mapboxgl 加载瓦片网格

mapboxgl 加载瓦片网格

时间:2024-08-07 16:27:35浏览次数:12  
标签:map const text 网格 bounds mapboxgl lngStep Math 加载

import mapboxgl from "mapbox-gl";
export default class GridLayer {
  constructor(map) {
    this.map = map;
    this.gridSourceId = "grid-source";
    this.gridLayerId = "grid-layer";
    this.labelSourceId = "label-source";
    this.labelLayerId = "label-layer";

    this.initGrid();
    this.map.on("moveend", () => this.updateGrid());
    this.map.on("zoomend", () => this.updateGrid());
  }

  initGrid() {
    this.map.addSource(this.gridSourceId, {
      type: "geojson",
      data: this.createGridData()
    });

    this.map.addLayer({
      id: this.gridLayerId,
      type: "line",
      source: this.gridSourceId,
      layout: {},
      paint: {
        "line-color": "#888",
        "line-width": 1
      }
    });

    // label文本显示需要在样式中设置glyphs
    this.map.addSource(this.labelSourceId, {
      type: "geojson",
      data: this.createLabelData()
    });

    this.map.addLayer({
      id: this.labelLayerId,
      type: "symbol",
      source: this.labelSourceId,
      layout: {
        "text-field": ["get", "text"],
        "text-size": 24,
        "text-offset": [0, 0],
        "text-font": ["Arial Regular"]
      },
      paint: {
        "text-color": "#fff", // 文本的颜色(可选,默认值为 #000000)
        "text-halo-color": "rgb(190,190,190)", // 文本的光晕颜色(可选,默认值为 rgba(0,0,0,0))
        "text-halo-width": 3 // 文本的光晕宽度(可选,值 >= 0,默认值为 0,单位:像素)
      }
    });
  }

  createGridData() {
    const bounds = this.map.getBounds();
    const zoom = Math.floor(this.map.getZoom());
    const tileCount = Math.pow(2, zoom);

    const lngStep = 360 / tileCount;
    const minLat = -85.05112878;
    const maxLat = 85.05112878;

    const minLng = Math.floor(bounds.getWest() / lngStep) * lngStep;
    const maxLng = Math.ceil(bounds.getEast() / lngStep) * lngStep;

    const lines = [];

    for (let lng = minLng; lng <= maxLng; lng += lngStep) {
      lines.push({
        type: "Feature",
        geometry: {
          type: "LineString",
          coordinates: [
            [lng, minLat],
            [lng, maxLat]
          ]
        }
      });
    }

    for (let y = 0; y <= tileCount; y++) {
      const lat = this.yTile2lat(y, zoom);
      lines.push({
        type: "Feature",
        geometry: {
          type: "LineString",
          coordinates: [
            [minLng, lat],
            [maxLng, lat]
          ]
        }
      });
    }

    return {
      type: "FeatureCollection",
      features: lines
    };
  }

  createLabelData() {
    const bounds = this.map.getBounds();
    const zoom = Math.floor(this.map.getZoom());
    const tileCount = Math.pow(2, zoom);

    const lngStep = 360 / tileCount;
    // const minLat = -85.05112878;
    // const maxLat = 85.05112878;
    // const minLng = Math.floor(bounds.getWest() / lngStep) * lngStep;
    // const maxLng = Math.ceil(bounds.getEast() / lngStep) * lngStep;

    // 通过经纬度计算瓦片信息,保证只绘制可视域范围内的瓦片
    let minxyz = this.lngLat2Tile([bounds.getWest(), bounds.getSouth()], zoom);
    let maxxyz = this.lngLat2Tile([bounds.getEast(), bounds.getNorth()], zoom);

    const labels = [];
    for (let x = minxyz.x; x <= maxxyz.x; x++) {
      for (let y = maxxyz.y; y <= minxyz.y; y++) {
        const lng = this.xTile2lng(x, zoom);
        const lat = this.yTile2lat(y, zoom);
        const nextLng = this.xTile2lng(x + 1, zoom);
        const nextLat = this.yTile2lat(y + 1, zoom);
        if (
          (lng >= bounds.getWest() || nextLng <= bounds.getEast()) &&
          (lat >= bounds.getSouth() || nextLat <= bounds.getNorth())
        ) {
          labels.push({
            type: "Feature",
            geometry: {
              type: "Point",
              coordinates: [(lng + nextLng) / 2, (lat + nextLat) / 2]
            },
            properties: {
              text: `Z: ${zoom}\nX: ${x}\nY: ${y}`
            }
          });
        }
      }
    }

    return {
      type: "FeatureCollection",
      features: labels
    };
  }

  //经纬度转瓦片序列号
  lngLat2Tile(coordinates, zoom) {
    const { x, y } = mapboxgl.MercatorCoordinate.fromLngLat({
      lng: coordinates[0],
      lat: coordinates[1]
    });

    const scale = Math.pow(2, zoom);
    const tileX = Math.floor(x * scale);
    const tileY = Math.floor(y * scale);
    return { x: tileX, y: tileY, z: zoom };
  }

  xTile2lng(x, zoom) {
    return (x / Math.pow(2, zoom)) * 360 - 180;
  }

  yTile2lat(y, zoom) {
    const n = Math.PI - (2 * Math.PI * y) / Math.pow(2, zoom);
    return (180 / Math.PI) * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n)));
  }

  updateGrid() {
    this.map.getSource(this.gridSourceId).setData(this.createGridData());
    this.map.getSource(this.labelSourceId).setData(this.createLabelData());
  }

  removeGridLayer() {
    this.map.removeLayer(this.gridLayerId);
    this.map.removeSource(this.gridSourceId);
    this.map.removeLayer(this.labelLayerId);
    this.map.removeSource(this.labelSourceId);
  }
}

 

 

标签:map,const,text,网格,bounds,mapboxgl,lngStep,Math,加载
From: https://www.cnblogs.com/xiaohanyanliu/p/18347311

相关文章

  • 保存/加载自定义 tf.keras.Model 时出现问题
    我正在构建一个作为自定义tf.keras.Model实现的自动编码器。虽然训练后的模型表现良好,但我无法正确保存并重新加载它。我已经尝试过model.save()方法和save_weights()但在这两种情况下,模型完全无法执行其任务。此自动编码器正在调用另外两个tf.keras.Model,即编码器和......
  • 类加载机制
    什么是类加载机制我们编写的Java文件都是以.java为后缀的文件,编译器会将我们编写的.java的文件编译成.class文件,简单来说类加载机制就是jvm从文件系统将一系列的class文件z转化为二进制流加载JVM内存中并生成一个该类的Class对象,为后续程序运行提供资源的动作。整体的......
  • Vue3中滚动加载更多数据
    <divclass="my-task-body-inner"ref="scrollContainer"@scroll="handleScroll"style="height:100%;overflow-y:auto;"></div>constscrollContainer=ref(null); consthandleScroll=()=>......
  • MapperScannerConfigurer中获取applicayion.yml配置,进行动态加载BasePackage
     由于在MapperScannerConfigurer的bean优先于@value,导致@value取出来的时候都是null,所以只能使用Environment来获取值importorg.mybatis.spring.mapper.MapperScannerConfigurer;importorg.springframework.beans.factory.annotation.Value;importorg.springframework......
  • pytorch 模型加载和保存
    模型加载torch.load(f,map_location=None,pickle_module=<module'pickle'from'/opt/conda/lib/python3.6/pickle.py'>,**pickle_load_args) map_location适用于修改模型能在gpu上运行还是cpu上运行。一般情况下,加载模型,主要用于预测新来的一组样本。预测的主要流程包......
  • python图表没有正确显示中文,这通常是因为matplotlib的默认设置不支持中文字符,或者相应
    如果图表没有正确显示中文,这通常是因为matplotlib的默认设置不支持中文字符,或者相应的字体没有正确加载。你可以通过指定支持中文的字体来解决这个问题。下面是如何设置matplotlib以确保能够在图表中显示中文的步骤:方法1:全局设置字体你可以修改matplotlib的全局配置,使......
  • [三、渲染控制法]4. LazyForEach:数据懒加载
    LazyForEach从提供的数据源中按需迭代数据,并在每次迭代过程中创建相应的组件。当在滚动容器中使用了LazyForEach,框架会根据滚动容器可视区域按需创建组件,当组件滑出可视区域外时,框架会进行组件销毁回收以降低内存占用。接口描述LazyForEach(dataSource:IDataSource,......
  • 继承的特点注意事项以及类的初始化顺序和加载顺序day08
    继承的好处提高了代码的复用性多个类相同的成员可以放到同一个类中提高了代码的维护性如果功能的代码需要修改,修改一处即可让类与类之间产生了关系,是多态的前提其实这也是继承的一个弊端:类的耦合性很强......
  • 【转载】ubuntu用户/linux用户登录后没有自动加载.bashrc
    版权声明:本文为CSDN博主「安安爸Chris」的原创文章,遵循CC4.0BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/mimiduck/article/details/120041171今天遇到一个问题,linux下某用户登陆后无法加在其自身的.bashrc,通过source.bashrc发现......
  • 七、分散加载说明
    分散加载说明以GD32F103ZE为例,分别用Keil、IAR和EmbeddedBuilder工具实现:将函数放置某个地址、将常量放置某个地址、将函数放在RAM中运行的三种效果。1、将led_toggle()函数放在0x08040000地址后。2、将tempbuf[1024]常量放在0x08020000地址后。3、将voidled_flow(void)......