前置说明
- 对于通过Arcgis-server直接发布的切片地图(不是图层),esri-leaflet可以对其进行解析与加载
- esri-leaflet本质上是对leaflet的layer进行了扩展,使其能够与map对象兼容,但没有对map进行扩展
- 因此,对于不是wkid不是3857(即leaflet的map默认投影)的切片地图,在叠加时一定要手工设置map的crs参数
- leaflet的map不会因为初始化layer的crs自动调整自己的crs
环境准备
准备切片服务
个人在arcgis-server上发布的切片服务元数据信息(节选)如下:
服务地址为http://localhost:6080/arcgis/rest/services/02_Tky_GDCGK_Tile/MapServer
{
"singleFusedMapCache": true,
"tileInfo": {
"rows": 256,
"cols": 256,
"dpi": 96,
"format": "PNG",
"compressionQuality": 0,
"origin": {
"x": -400,
"y": 399.9999999999998
},
"spatialReference": {
"wkid": 4490,
"latestWkid": 4490
},
"lods": [
{
"level": 0,
"resolution": 0.00951784402332112,
"scale": 4000000
},
{
"level": 1,
"resolution": 0.00475892201166056,
"scale": 2000000
},
{
"level": 2,
"resolution": 0.00237946100583028,
"scale": 1000000
},
{
"level": 3,
"resolution": 0.00118973050291514,
"scale": 500000
},
{
"level": 4,
"resolution": 0.00059486525145757,
"scale": 250000
},
{
"level": 5,
"resolution": 0.000297432625728785,
"scale": 125000
},
{
"level": 6,
"resolution": 0.00015228550437313792,
"scale": 64000
},
{
"level": 7,
"resolution": 0.00007614275218656896,
"scale": 32000
},
{
"level": 8,
"resolution": 0.00003807137609328448,
"scale": 16000
},
{
"level": 9,
"resolution": 0.00001903568804664224,
"scale": 8000
}
]
}
//其他内容省略...
}
安装投影转换包
npm install proj4 proj4leaflet
安装leaflet/esri-leaflet支持包
npm install leaflet esri-leaflet
操作步骤
- 定义与切片地图lods层级/原点一致的crs对象
- 创建地图并指定目标crs
- 创建图层并指定初始化参数
- 加载到地图中
实例代码
import React, { useEffect } from 'react';
import L from "leaflet"
import * as esri from "esri-leaflet"
import 'proj4/dist/proj4-src';
import 'proj4leaflet/src/proj4leaflet';
import "../node_modules/leaflet/dist/leaflet.css";
function EsriTileLayer(props) {
useEffect(() => {
let CRS_4490 = new L.Proj.CRS("EPSG:4490", "+proj=longlat +ellps=GRS80 +no_defs", {
resolutions: [
0.00951784402332112,
0.00475892201166056,
0.00237946100583028,
0.00118973050291514,
5.9486525145757E-4,
2.97432625728785E-4,
1.5228550437313792E-4,
7.614275218656896E-5,
3.807137609328448E-5,
0.00274658203125,
0.001373291015625,
1.903568804664224E-5
],
origin: [-400.0, 399.9999999999998],
});
let map = L.map('leaflettilelayer_map', { crs: CRS_4490 }).setView([29.677, 106.914], 4);
let tileLayer = esri.tiledMapLayer({ url: 'http://localhost:6080/arcgis/rest/services/02_Tky_GDCGK_Tile/MapServer' });
tileLayer.addTo(map);
}, [])
return (
<div id="leaflettilelayer_map" style={{ width: "100%", height: "800px" }}></div>
);
}
export default EsriTileLayer;
代码说明
- 这里需要定义的是proj4leaflet中的crs,因此必须要有缩放层级和原点信息
- crs中的resolutions和origin信息,应该与切片地图的缩放层级保持一致,否则会出现切片行列号计算错误,而找不到切片的问题
- 与dynamicMapLayer不一样,tileMapLayer的url是写在构造函数的config对象参数中的,而不是一个单独的函数参数
- 这里的url不需要加图层索引号
- 一定要引入"leaflet.css"的样式文件,否则切片加载会出现错位的问题
扩展内容
tileMaplayer提供了metadata方法获取当前地图服务的元数据信息,因此可以通过该方法动态的加载当前地图服务的lods和origin信息
function EsriTileLayer2(props) {
useEffect(() => {
let layer = esri.tiledMapLayer({ url: "http://localhost:6080/arcgis/rest/services/02_Tky_GDCGK_Tile/MapServer" });
layer.metadata((error, context) => {
let { spatialReference, lods, origin } = context.tileInfo
let current_crs = new L.Proj.CRS(factory.toDefName(spatialReference.wkid),
factory.toDefStr(spatialReference.wkid),
factory.parseLods(lods, origin))
let map = L.map('leaflettilelayer2_map', { crs: current_crs }).setView([29.677, 106.914], 4);
layer.addTo(map)
})
}, [])
return (
<div id="leaflettilelayer2_map" style={{ width: "100%", height: "800px" }}></div>
);
}
export default EsriTileLayer2;
其中factory的各种方法其实就是将context中的内容解析并转换为crs定义所需要的形式