Openlayers加载ArcGIS矢量瓦片出现水平偏移问题求助
问题原因与解决方案
核心原因
我之前遇到过完全类似的问题,这个10000米偏移的核心原因是:虽然你用的是同一投影(EPSG:25832),但OpenLayers默认的瓦片网格(TileGrid)参数,和ArcGIS Pro生成的矢量瓦片服务的瓦片网格规则不匹配。ArcGIS的矢量瓦片会采用自定义的网格标准,包括瓦片原点、分辨率层级、瓦片范围等,这些参数和OpenLayers针对EPSG:25832的默认TileGrid不一致,就会导致图层出现偏移。
解决步骤
要解决这个问题,你需要创建一个和ArcGIS矢量瓦片服务完全匹配的TileGrid,并将其应用到矢量瓦片数据源上:
获取ArcGIS矢量瓦片服务的元数据
访问你的矢量瓦片服务根地址,查看返回的tileInfo字段,里面包含了关键的网格参数:origin:瓦片网格的原点坐标resolutions:每个缩放层级对应的分辨率数组tileSize:瓦片的像素尺寸
创建匹配的OpenLayers TileGrid
用从元数据中拿到的参数,创建自定义的ol.tilegrid.TileGrid实例。将自定义TileGrid应用到VectorTileSource
在ol.source.VectorTile的配置中添加tileGrid属性,指向你创建的自定义网格。
修改后的代码示例
// 修正proj4定义的引号问题 proj4.defs('EPSG:25832', "+proj=utm +zone=32 +ellps=GRS80 +units=m +no_defs"); ol.proj.proj4.register(proj4); var myProjection = ol.proj.get('EPSG:25832'); myProjection.setExtent([130000, 5661139.2, 1378291.2, 6500000]); // 从ArcGIS矢量瓦片服务元数据中获取的网格参数 const arcgisTileInfo = { origin: [120000, 6500000], // 服务元数据中的原点 resolutions: [1638.4, 819.2, 409.6, 204.8, 102.4, 51.2, 25.6, 12.8, 6.4, 3.2, 1.6, 0.8, 0.4, 0.2, 0.1], // 对应层级的分辨率 tileSize: 512 }; // 创建匹配的TileGrid const myTileGrid = new ol.tilegrid.TileGrid({ origin: arcgisTileInfo.origin, resolutions: arcgisTileInfo.resolutions, tileSize: arcgisTileInfo.tileSize, extent: myProjection.getExtent() }); var resturl = 'https://bragdev3.gis.dk/arcgis/rest/services/Plandistrikter2/MapServer'; const mousePositionControl = new ol.control.MousePosition({ coordinateFormat: ol.coordinate.createStringXY(4), projection: 'EPSG:25832', className: 'custom-mouse-position', target: document.getElementById('mouse-position'), }); var map = new ol.Map({ controls: ol.control.defaults().extend([mousePositionControl]), target: 'map', view: new ol.View({ center: [0, 0], zoom: 10, projection: myProjection }), layers: [ new ol.layer.VectorTile({ source: new ol.source.VectorTile({ format: new ol.format.MVT(), tileGrid: myTileGrid, // 应用自定义瓦片网格 projection: 'EPSG:25832', minZoom: 0, maxZoom: 15, wrapX: false, url: 'https://bragdev3.gis.dk/arcgis/rest/services/Hosted/Plandistrikter2/VectorTileServer/tile/{z}/{y}/{x}.pbf' }), tileSize: 512, }), new ol.layer.Tile({ title:'ArcGISRest', source: new ol.source.TileArcGISRest({ url: resturl, params: { FORMAT: "png32", // 修正引号问题 LAYERS: "show:0", DPI: 96 }, projection: ol.proj.get("EPSG:25832"), // 修正引号问题 }) }) ], }); map.on('moveend', move); function move(event) { var info = document.getElementById('info'); const extent = map.getView().calculateExtent(map.getSize()); const resolution = map.getView().getResolution(); const zoom = map.getView().getZoom(); info.innerText = 'zoom: ' + zoom + ' resolution: ' + resolution + ' extent:' + extent; info.style.opacity = 1; } var info = document.getElementById('info'); function showInfo(event) { var features = map.getFeaturesAtPixel(event.pixel); if (!features || features.length == 0) { info.innerText = ''; info.style.opacity = 0; return; } var properties = features[0].getProperties(); info.innerText = JSON.stringify(properties, null, 2); info.style.opacity = 1; } var center = [706000,6216062]; map.getView().setCenter(center); map.getView().setZoom(6);
额外注意点
- 我还修正了你代码里的两处引号错误:proj4定义里的多余转义引号,以及TileArcGISRest投影参数里的错误引号,这些也可能导致潜在的投影解析问题。
- 确保你从ArcGIS服务元数据中获取的
origin和resolutions是准确的,如果服务更新过,这些参数可能会变化,建议直接从服务页面复制最新值。
内容的提问来源于stack exchange,提问作者lars
相关产品推荐
相关产品推荐

