openlayers加载arcgis的VectorTileServer服务图层
url示例:http://127.0.0.1/arcgis/rest/services/Hosted/JCDLDT_YX_2K/VectorTileServer
js
/**
* 加载ArcGis矢量瓦片
* @param options
*/
public async loadArcGisVectorTileLayer(options: IaddArcgisLayerConfig) {
const metadata = await fetch(`${options.url}?f=pjson`).then((r) => r.json());
const tileGrid: any = this.buildTileGridFromArcGIS(metadata);
console.log('Full metadata:', metadata);
console.log('Styles:', metadata.styles); // 查看 styles 信息
const source = new VectorTileSource({
format: new MVT(),
url: `${options.url}/tile/{z}/{y}/{x}.pbf`,
tileGrid,
// projection: `EPSG:${metadata.fullExtent.spatialReference.wkid}`,
projection: `EPSG:4490`,
wrapX: true,
});
const layer = new VectorTileLayer({
source,
zIndex: options.index,
});
layer.setProperties({
id: options.layerId,
group: options.group,
record: options,
});
console.log(layer, 'layer');
this.map.addLayer(layer);
// 加载并应用样式
const styleJson = await fetch(`${options.url}/resources/styles/root.json`).then(r => r.json());
// 修正样式中的资源路径
if (styleJson.sprite) {
styleJson.sprite = `${options.url}/resources/sprites/sprite`;
}
if (styleJson.glyphs) {
styleJson.glyphs = `${options.url}/resources/fonts/{fontstack}/{range}.pbf`;
}
if (styleJson.sources?.esri) {
delete styleJson.sources.esri.url;
styleJson.sources.esri.tiles = [`${options.url}/tile/{z}/{y}/{x}.pbf`];
styleJson.sources.esri.tileSize = 512;
}
// 构建切片网格
const resolutions = metadata.tileInfo.lods
.sort((a, b) => a.level - b.level)
.map(lod => lod.resolution);
await applyStyle(layer, styleJson, "esri", { resolutions });
}
/**
* 根据 ArcGIS VectorTileServer 的 pjson 构建 OpenLayers TileGrid
*/
public buildTileGridFromArcGIS(metadata: any): TileGrid {
if (!metadata?.tileInfo) {
throw new Error('ArcGIS VectorTileServer 元数据缺少 tileInfo');
}
const tileInfo = metadata.tileInfo;
const fullExtent = metadata.fullExtent;
// extent
const extent: [number, number, number, number] = [
fullExtent.xmin,
fullExtent.ymin,
fullExtent.xmax,
fullExtent.ymax,
];
// origin
const origin: [number, number] = [
tileInfo.origin.x,
tileInfo.origin.y,
];
const tileSize: number = tileInfo.cols;
// resolutions 直接使用 metadata 中的值
const resolutions: number[] = tileInfo.lods
.sort((a: any, b: any) => a.level - b.level)
.map((lod: any) => lod.resolution);
return new TileGrid({
extent,
origin,
tileSize,
resolutions,
});
}
创建4490经纬度地图
js
const mapDiv: any = document.querySelector('.mapDiv');
const projection = new Projection({
code: `EPSG:4490`,
units: 'degrees',
global: false, // 是否全局
});
this.projection = projection;
const map = new Map({
target: mapDiv,
layers: [],
view: new View({
projection,
minZoom: 6,
maxZoom: 21,
center: [102, 25], // 云南中心点附近
zoom: 8,
// 关闭无级缩放地图
smoothResolutionConstraint: true,
// 设置边界范围
extent: [98, 20.5, 106, 30],
// 确保地图中心点不能移动到边界外
constrainOnlyCenter: true,
}),
controls: [],
});
