OpenLayers 6中能否为静态栅格图片源设置旋转和缩放参数
OpenLayers 6 原生实现类似ol-ext GeoImage效果的方案
核心实现思路
不需要引入ol-ext库,通过自定义像素投影与目标投影的坐标变换规则,直接将你计算得到的仿射参数绑定到投影变换逻辑中,即可实现静态图片的缩放、旋转、地理空间对齐效果。
方案1:自定义投影变换(推荐,性能最优)
import { Projection } from 'ol/proj'; import { register } from 'ol/proj/proj4'; import proj4 from 'proj4'; import ImageLayer from 'ol/layer/Image'; import Static from 'ol/source/ImageStatic'; // 你的预设参数 const imagurl = '你的图片地址'; const imageData = { width: 替换为实际图片宽度, height: 替换为实际图片高度 }; const scaling = [327.805670381418, 327.805670381418]; const rotation = -0.1310210334156003; const transformation = [7179251.8557908312, 6022627.228704552]; // 目标投影下的图片中心点坐标,这里默认是EPSG:3857 const targetProjCode = 'EPSG:3857'; const pixelProjCode = 'xkcd-image'; // 1. 初始化自定义像素投影 const pixelExtent = [0, 0, imageData.width, imageData.height]; const pixelProjection = new Projection({ code: pixelProjCode, units: 'pixels', extent: pixelExtent, }); // 2. 预计算变换通用参数 const pixelCenter = [imageData.width / 2, imageData.height / 2]; // 图片自身的像素中心点 const cosRot = Math.cos(rotation); const sinRot = Math.sin(rotation); // 3. 定义正反坐标变换逻辑 // 像素坐标转目标地理坐标 function pixelToTarget(pixelCoord) { const dx = pixelCoord[0] - pixelCenter[0]; const dy = pixelCoord[1] - pixelCenter[1]; // 缩放+旋转+位移,注意y轴取反适配像素与地理坐标的方向差异 const scaledDx = dx * scaling[0]; const scaledDy = dy * scaling[1]; const rotatedX = scaledDx * cosRot - scaledDy * sinRot; const rotatedY = scaledDx * sinRot + scaledDy * cosRot; return [ transformation[0] + rotatedX, transformation[1] - rotatedY ]; } // 目标地理坐标转像素坐标 function targetToPixel(targetCoord) { const dx = targetCoord[0] - transformation[0]; const dy = transformation[1] - targetCoord[1]; const rotatedX = dx * cosRot + dy * sinRot; const rotatedY = -dx * sinRot + dy * cosRot; const scaledDx = rotatedX / scaling[0]; const scaledDy = rotatedY / scaling[1]; return [ pixelCenter[0] + scaledDx, pixelCenter[1] + scaledDy ]; } // 4. 注册变换规则到OpenLayers proj4.defs(pixelProjCode, `+proj=longlat +axis=enu +no_defs`); proj4.defs(targetProjCode, 'EPSG:3857'); proj4.addTransform(pixelProjCode, targetProjCode, pixelToTarget); proj4.addTransform(targetProjCode, pixelProjCode, targetToPixel); register(proj4); // 5. 生成图层直接使用即可 const imageLayer = new ImageLayer({ source: new Static({ url: imagurl, projection: pixelProjection, imageExtent: pixelExtent, }), });
方案2:无proj4依赖的简化方案(适合小图片场景)
如果不想引入proj4依赖,也可以通过图层自定义渲染逻辑直接应用变换:
import ImageLayer from 'ol/layer/Image'; import Static from 'ol/source/ImageStatic'; import Style from 'ol/style/Style'; const imagurl = '你的图片地址'; const imageData = { width: 替换为实际图片宽度, height: 替换为实际图片高度 }; const scaling = [327.805670381418, 327.805670381418]; const rotation = -0.1310210334156003; const transformation = [7179251.8557908312, 6022627.228704552]; const imageLayer = new ImageLayer({ source: new Static({ url: imagurl, projection: 'EPSG:3857', imageExtent: [0, 0, imageData.width, imageData.height], }), style: new Style({ renderer: (coords, state) => { const ctx = state.context; const img = state.context.canvas; ctx.save(); // 按顺序应用变换:位移->旋转->缩放->对齐图片左上角 ctx.translate(transformation[0], transformation[1]); ctx.rotate(rotation); ctx.scale(scaling[0], -scaling[1]); ctx.translate(-imageData.width/2, -imageData.height/2); ctx.drawImage(img, 0, 0, imageData.width, imageData.height); ctx.restore(); } }) });
注意事项
- 如果你的目标投影不是EPSG:3857,只需修改
targetProjCode和对应proj4的投影定义即可 - 若图片y轴方向和地理投影方向一致,可移除变换逻辑中的y轴取反操作
内容的提问来源于stack exchange,提问作者developer g
相关产品推荐
相关产品推荐

