You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 19:57:04