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

OpenLayers导出带比例尺PNG地图不显示及报错问题咨询

OpenLayers 导出带比例尺的PNG/PDF解决方案

问题原因

  • 现有代码导出PNG无比例尺:绘制逻辑顺序错误,你先在导出画布上绘制了比例尺,之后才把地图图层的内容绘制到同一画布,图层内容直接覆盖了比例尺
  • Cannot read properties of undefined (reading 'beginPath')报错:你参考的旧版本示例依赖低版本OpenLayers的postcompose事件返回的上下文结构,你当前使用的OpenLayers版本接口变更,导致获取到的上下文为undefined

修复后的PNG导出代码

document.getElementById('export-png').addEventListener('click', function() {
  map.once('postcompose', function(event) {
    var canvas = document.createElement('canvas');
    var size = map.getSize();
    canvas.width = size[0];
    canvas.height = size[1];
    var mapContext = canvas.getContext('2d');

    // 第一步:先绘制所有地图图层
    Array.prototype.forEach.call(
      document.querySelectorAll('.ol-layer canvas'),
      function (layerCanvas) {
        if (layerCanvas.width > 0) {
          var opacity = layerCanvas.parentNode.style.opacity;
          mapContext.globalAlpha = opacity === '' ? 1 : Number(opacity);
          var transform = layerCanvas.style.transform;
          // 解析变换矩阵
          var matrix = transform
            .match(/^matrix\(([^\(]*)\)$/)[1]
            .split(',')
            .map(Number);
          CanvasRenderingContext2D.prototype.setTransform.apply(
            mapContext,
            matrix
          );
          mapContext.drawImage(layerCanvas, 0, 0);
        }
      }
    );

    // 第二步:图层绘制完成后再绘制比例尺,避免被覆盖
    var resolution = map.getView().getResolution();
    // 可根据需求调整比例尺长度,这里以200米为例
    var scaleLength = 200 / resolution;
    var scaleY = size[1] - 20; // 调整y坐标避免文字被画布边缘截断
    mapContext.setTransform(1, 0, 0, 1, 0, 0); // 重置变换矩阵,避免比例尺受图层变换影响
    mapContext.strokeStyle = "#0000FF";
    mapContext.lineWidth = 5;
    mapContext.beginPath();
    mapContext.moveTo(10, scaleY);
    mapContext.lineTo(10 + scaleLength, scaleY);
    mapContext.stroke();
    mapContext.font = "20px Arial";
    mapContext.fillStyle = "#0000FF";
    mapContext.fillText("200m", 10, scaleY - 5);

    // 下载逻辑保持不变
    if (navigator.msSaveBlob) {
      var imgName = prompt("Please provide the name", "survey_map");
      navigator.msSaveBlob(canvas.msToBlob(), imgName + '.png');
    } else {
      var link = document.getElementById('image-download');
      link.href = canvas.toDataURL();
      link.download = 'survey_map.png';
      link.click();
    }
  });
  map.renderSync();
});

如果需要和页面上显示的ScaleLine控件完全一致,不需要自己计算比例尺,可以引入html2canvas类库,将页面上的比例尺DOM元素转成图像后绘制到导出画布上,避免手动计算分辨率出现的误差。

PDF导出添加比例尺实现方式

导出PDF可借助jsPDF类库实现,逻辑如下:

  1. 按照上述修复后的逻辑生成带比例尺的PNG base64资源
  2. 初始化jsPDF实例,根据导出画布的尺寸设置PDF页面大小
  3. 调用addImage方法将生成的PNG添加到PDF中,此时PNG已自带比例尺,无需额外绘制
  4. 调用save方法导出PDF文件即可

内容的提问来源于stack exchange,提问作者Geographos

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 02:06:00