两个图层各用一套坐标系,叠上去错开半屏
底图正常显示,叠加的规划图却整体偏右上,缩放越大偏得越多。
现象
View 设为 EPSG:3857,底图用 OSM 正常。
叠加的第一个图层是 GeoJSON,坐标是经纬度,L.geoJSON 那套写法搬过来后直接可用;
第二个图层是 ImageStatic 配一张覆盖
116.0°E ~ 116.6°E、39.7°N ~ 40.1°N 的规划图 PNG,
用 extent: [116.0, 39.7, 116.6, 40.1] 添加。
结果规划图缩小并贴在左上角,与底图错开大半个屏幕。
把 extent 改成米值 [12913000, 4820000, 12980000, 4865000] 后图变大但仍偏,
而且在北纬 40° 附近纵向被压扁。
原因
OpenLayers 的所有图层都必须声明自己的数据坐标系 projection。
不声明时,ImageStatic 默认使用 View 的投影(这里是 3857),
于是 extent 里的 116.0 被当作 116 米,整张图缩成 0.6 米宽,贴在原点附近。
改成米值后地图位置对了,但 ImageStatic 是直接把图片拉伸铺满 extent,
不做逐像素重投影,所以在 3857 下按经纬度矩形铺图会纵向压扁约 1.3 倍。
排查过程
- 打印每个图层的
layer.getSource().getProjection().getCode()。 - 与
map.getView().getProjection().getCode()比对,不一致又没有声明重投影,就会错位。 - 看 extent 数值量级:十位以内是度,七位以上是米。
- 把
extent用ol.proj.transformExtent转成 View 投影后再加,看是否对齐。
console.log(view.getProjection().getCode()); // EPSG:3857
console.log(imgLayer.getSource().getProjection().getCode()); // EPSG:3857(默认)
console.log(extent); // [116, 39.7, 116.6, 40.1] 单位是度,与 3857 不匹配
解决方案
数据是什么坐标系就声明什么,让 OpenLayers 负责重投影;
对不做重投影的 ImageStatic,先把 extent 转到 View 投影。
import { transformExtent } from 'ol/proj';
// 1. 让 ImageStatic 声明自己打哪儿来
new ImageLayer({
source: new ImageStatic({
url: '/data/plan.png',
projection: 'EPSG:4326', // 关键
imageExtent: [116.0, 39.7, 116.6, 40.1]
})
});
// 2. 或者直接把 extent 转成 View 的投影(推荐,裁剪更准)
const ext3857 = transformExtent([116.0, 39.7, 116.6, 40.1], 'EPSG:4326', 'EPSG:3857');
new ImageLayer({
source: new ImageStatic({
url: '/data/plan.png',
projection: 'EPSG:3857',
imageExtent: ext3857
})
});
// 3. 矢量图层同理
new VectorLayer({
source: new VectorSource({
url: '/data/roads.geojson',
format: new GeoJSON({ dataProjection: 'EPSG:4326', featureProjection: 'EPSG:3857' })
})
});
验证
规划图四角应与底图上对应的道路交叉口重合,误差小于 1 个像素; 在 10、12、14 三个缩放级别分别检查,偏差不应随级别放大。
const ext = transformExtent([116.0, 39.7, 116.6, 40.1], 'EPSG:4326', 'EPSG:3857');
console.log(ext.map(v => v.toFixed(0)));
// 约 [12912986, 4818065, 12979685, 4865202]
适用版本
| 库 | 版本 | 说明 |
|---|---|---|
| OpenLayers | 7.x ~ 9.x | 图层 projection 未声明时继承 View 投影 |
| ol/proj | 同版本 | transformExtent 支持 4326/3857 免注册 |
| Leaflet | 1.x | L.imageOverlay 的 bounds 必须是 LatLng,无需转换 |
经纬志(2026)。《两个图层各用一套坐标系,叠上去错开半屏》。https://www.jingweizhi.com/cookbook/overlay-two-crs.html(访问日期 2026-11-03)。