leaflet加载本地Geoserver发布的WMTS

1. leaflet 加载本地geoserver 的 WMTS

1.1. 安装wmts插件

原生leaflet不支持 wmts 图层,需要到插件库中选则需要的 wmts 图层插件类型。

1.1.1. 可以到 leaflet 官网上查找需要的插件。

Basemap formats
在这里插入图片描述

1.1.2. npm 插件搜索

也可以在 npm 官网上搜索关键词 leaflet-wmtsleaflet-wmts 找到相关插件。
npm官网
在这里插入图片描述

在这里插入图片描述
ps: github 上的项目可以在 npm 上找到对应的项目, 可以通过如

npm i leaflet.wmts

安装对应的包。

1.2. Leaflet 访问 Geoserver 的 WMTS

  • 我们以 npm 官网上最流行的 leaflet.wmts 为例:

npm i leaflet.wmts

  • 代码
import 'leaflet.wmts'

var matrixIds = [];
for (var i=0; i<22; ++i) {
   matrixIds[i] = {
     identifier : "" + i,
     topLeftCorner : new L.LatLng(90, -180)
   };
 }
const mapUrl = "http://localhost:8080/geoserver/nanjingjiaoguanju/gwc/service/wmts"
const ign =new L.TileLayer.WMTS(mapUrl,
    {
         layer: "myworkspace:tuceng1",//图层名称
         tilematrixSet: "EPSG:900913",//GeoServer使用的网格名称
         style: "normal",
         format: 'image/png',
         // maxZoom: 16,
         // minZoom: 10,
         matrixIds: matrixIds,
     }
   );
ign.addTo(leafletMap)
# 2. Openlayers 加载本地 geoserver 的 WMTS


2. Openlayers 访问 Geoserver 的 WMTS

2.1. 在 vue3 中结合 openlayers 访问 wmts

<template>

    <div>
      <div id="mapdiv" class="map" tabindex="0"></div>
      <button @click="loadWMS">加载WMS</button>
      <button @click="loadWMTS">加载WMTS</button>
    </div>
</template>

<script>

import Map from 'ol/Map.js';
import TileLayer from 'ol/layer/Tile.js';
import View from 'ol/View.js';
import { ref,onMounted } from 'vue';
import {FullScreen, defaults as defaultControls} from 'ol/control.js';
import WMTS from 'ol/source/WMTS.js';
import WMTSTileGrid from 'ol/tilegrid/WMTS.js';
import {get as getProjectionByEPSG} from 'ol/proj';
import {getWidth,getTopLeft} from 'ol/extent';

export default {
  name: 'BasicMapContainer',
  props: {
  },
  setup(){
    var gridsetName = 'EPSG:4326';
    const myprojection = getProjectionByEPSG(gridsetName);
    const projectionExtent = myprojection.getExtent();
    const size = getWidth(projectionExtent) / 256;
    const zoomlevelcount = 22
    const resolutions = new Array(zoomlevelcount);
    const matrixIds = new Array(zoomlevelcount);


    // for (let z = 0; z < 19; ++z) {
    //   // generate resolutions and matrixIds arrays for this WMTS
    //   resolutions[z] = size / Math.pow(2, z);
    //   matrixIds[z] = z;
    // }

    for (let z = 1; z < zoomlevelcount+1; ++z) {
      // generate resolutions and matrixIds arrays for this WMTS
      resolutions[z-1] = size / Math.pow(2, z);
      matrixIds[z-1] = myprojection.code_ +":"+ (z-1);
    }

    console.log("resolutions = ",resolutions);
    console.log("matrixIds = ",matrixIds);
    
    const baseUrl =  'http://localhost:8090/geoserver/myworkspace/gwc/service/wmts';

    const tileGridSet = new WMTSTileGrid({
          tileSize: [256,256],
          extent: [-180.0,-90.0,180.0,90.0],
          origin: [-180.0, 90.0],
          resolutions: resolutions,
          matrixIds: matrixIds
        });


    var source = new WMTS({
	        url: baseUrl,
	        layer: 'CHINA_county_region_2015',
	        matrixSet: gridsetName,
	        format: 'image/png',
	        projection:myprojection,
	        tileGrid: new WMTSTileGrid({
	          origin: getTopLeft(projectionExtent),
	          resolutions: resolutions,
	          matrixIds: matrixIds,
	        }),
          style: '',
	        wrapX: true,
      })

    let mapdiv = ref(null);
    let map  = new Map({
                  controls: defaultControls().extend([new FullScreen()]),
                  layers: [
                    new TileLayer({
                      source: source,
                    }),
                  ],
                  view: new View({
                    center: [0, 0],
                    projection: myprojection,
                    zoom: 2,
                  }),
                })
                
    onMounted(() => {
      console.log("组件已经挂载了")
      map.setTarget("mapdiv");
    })
  
    return {
         mapdiv,
    }
  },

  
   
}


</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style>
      #mapdiv {
        position: relative;
        width: 100%;
        height: 700px;
      }
      
      /* 缩放控件的样式设置 */
      .ol-zoom{
        right: 50px;
        position: absolute;
        top: 80px;
      }

      
      /* 缩放控件的样式设置 */
      .ol-rotate{
        right: 50px;
        position: absolute;
        top: 120px;
      }

      /* 全屏控件的样式设置 */
      .ol-full-screen {
        right: 50px;
        position: absolute;
        top: 50px;
      }
    
</style>

3. WMTS 相关参数

3.1. tileGrid

Tile Matrix Set,瓦片所在空间的几何结构。在平铺的地图图层中,空间的表示被约束在一组离散的参数中。Tile Matrix Set定义了这些参数。每个 Tile Matrix Set 包含一个或多个Tile Matrix,用于定义该坐标参考系统的Tile

3.1.1. Tile Matrix 相关参数

每个Tile Matrix由以下几个参数定义:

  • Scale Denominator
    Scale Denominato = 像素代表的地表实际距离 / 像素尺寸
  • TileHeight, TileWidth
    以像素个数计量的 Tile
  • TileMatrixMinX, TileMatrixMaxY
    TileMatrix 最大的y轴坐标 TileMatrixMaxY,最小的x轴坐标 TileMatrixMinX。(TileMatrixMinX,TileMatrixMaxY)表示 TileMatrix 左上角点 (TopLeftCorner) 的坐标。
  • MatrixWidth,MatrixHeight
    MatrixWidth,MatrixHeight分别为 TileMatrix 在X轴,Y轴上瓦片的个数。
    在这里插入图片描述

3.1.2. tileGrid 模型结构

每个 Tile Matrix Set 根据自己包含的 Tile Matrix 定义了一组缩放级别(如下图)。每个地图图层可以应用一种或多种 Tile Matrix Set ,尽管如此,服务器似乎喜欢为 不同的地图图层提供相同的 Tile Matrix SetTile Matrix 针对某一缩放级别进行了优化并对这个Tile Matrix 进行标识。由于 pixel alignment 问题,不同尺度下的Tile matrix 的边界框会有轻微的差别。
在这里插入图片描述

3.1.3. 计算 Tile Matrix 右下角点的坐标 (tileMatrixMaxX,tileMatrixMinY)

pixelSpan = scaleDenominator × 0.00028 / metersPerUnit(crs);
tileSpanX = tileWidth × pixelSpan;
tileSpanY = tileHeight × pixelSpan;
tileMatrixMaxX = tileMatrixMinX + tileSpanX × matrixWidth;
tileMatrixMinY = tileMatrixMaxY - tileSpanY × matrixHeight;

3.1.4. openlayers 中 WMTSTileGrid 对象的使用

const projection = getProjection('EPSG:3857');
const projectionExtent = projection.getExtent();
const size = getWidth(projectionExtent) / 256;
const resolutions = new Array(19);
const matrixIds = new Array(19);

for (let z = 1; z < zoomlevelcount+1; ++z) {
      // generate resolutions and matrixIds arrays for this WMTS
      resolutions[z-1] = size / Math.pow(2, z);
      matrixIds[z-1] = myprojection.code_ +":"+ (z-1);
    }

const tileGridSet = new WMTSTileGrid({
          tileSize: [256,256],
          extent: [-180.0,-90.0,180.0,90.0],
          origin: [-180.0, 90.0],
          resolutions: resolutions,
          matrixIds: matrixIds
        });

3.1.5. GeoServer源码中GridSetFactory.java中创建GridSet的方法:

public static GridSet createGridSet(String name, SRS srs, BoundingBox extent, boolean alignTopLeft, int levels,
 Double metersPerUnit, double pixelSize, int tileWidth, int tileHeight, boolean yCoordinateFirst) {
    double extentWidth = extent.getWidth();
    double extentHeight = extent.getHeight();
    double resX = extentWidth / (double)tileWidth;//48.37030696171132
    double resY = extentHeight / (double)tileHeight;//42.398664126933
    int tilesWide;
    int tilesHigh;
    if (resX <= resY) {
        tilesWide = 1;
        tilesHigh = (int)Math.round(resY / resX);
        resY /= (double)tilesHigh;
    } else {
        tilesHigh = 1;
        tilesWide = (int)Math.round(resX / resY); //1
        resX /= (double)tilesWide;//48.37030696171132
    }

    //取这两个方向上的像素最大值为当前比例尺下的像素尺寸
    double res = Math.max(resX, resY);//48.37030696171132
    
    //根据开始的边界bounds的左上角(切图原点),重新确定边界
    double adjustedExtentWidth = (double)(tilesWide * tileWidth) * res;
    double adjustedExtentHeight = (double)(tilesHigh * tileHeight) * res;
    BoundingBox adjExtent = new BoundingBox(extent);
    adjExtent.setMaxX(adjExtent.getMinX() + adjustedExtentWidth);
    if (alignTopLeft) {
        adjExtent.setMinY(adjExtent.getMaxY() - adjustedExtentHeight);
    } else {
        adjExtent.setMaxY(adjExtent.getMinY() + adjustedExtentHeight);
    }

    double[] resolutions = new double[levels];
    resolutions[0] = res;

    for(int i = 1; i < levels; ++i) {
        resolutions[i] = resolutions[i - 1] / 2.0D;
    }

    return createGridSet(name, srs, adjExtent, alignTopLeft, resolutions, (double[])null, metersPerUnit, pixelSize, (String[])null, tileWidth, tileHeight, yCoordinateFirst);
}
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值