首页 > 解决方案 > HTML5 Canvas DrawImage Safari 12.0 错误(在 iOS 12.1/Mac OS Mojave 上测试)

问题描述

最近在处理CanvasRenderingContext2D.drawImage()Canvas 2D API 的方法时发现了这个错误

void ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);

在此处输入图像描述

和参数应该是源图像的子矩形左上角sx的和坐标,用于绘制到目标上下文中。(来源:Mozilla)当提供小于 0(负值)的值时,Safari 浏览器上的工作方式不同。syx-axisy-axis

其他浏览器(经过测试的 ChromesxMicrosoft Edge )的负值可以按预期工作,方法是将提到的左上角重新定位到和的负边syx-axisy-axis

在此处输入图像描述


但是在Safari上,将左上角坐标的负值重置为sx并影响源图像的子矩形,以绘制到目标上下文中。sy0,0RIGHT BOTTOM CORNER

在此处输入图像描述

这是附加的画布演示片段在 Chrome 和 Safari 上呈现的方式(轮廓是画布的边界)在此处输入图像描述

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const image = document.getElementById('source');

onload = e =>
  ctx.drawImage(image, -40, -160, 300, 290, 0, 0, 300, 290);
canvas {
  border: 1px solid black;
}
<canvas id="canvas" width="300" height="290"></canvas>
<div style="display:none;">
  <img id="source" src="https://i.stack.imgur.com/NS35G.jpg">
</div>

任何解决此问题的方法肯定会有所帮助。

编辑:源宽度和源高度不超过实际图像的宽度或高度。

标签: htmlcanvassafarihtml5-canvasmobile-safari

解决方案


这是我所经历的。

我的代码是基于 Chrome 创建的

  renderImage(ctx) {
    if (this.$$.source) {
      const { image } = ... // html img tag with src

      const { viewport } = this.$$;
      ctx.drawImage(
        image,
        viewport.x,
        viewport.y,
        viewport.width,
        viewport.height,
        0,
        0,
        this.canvasWidth,
        this.canvasHeight
      );
    }
  • viewport(x, y, width,height) - 要渲染的 img 的部分区域
  • 0, 0, canvasWidth, canvasHeight - 画布区域

该代码在 chrome 中运行良好,但在 safari 中运行良好

如果 sx 或 sy 为负数,解决方法是偏移目标尺寸

  renderImage(ctx) {
    if (this.$$.source) {
      const { image } = ... // html img tag with src

      const { viewport } = this.$$;
      const offsetX = viewport.x < 0 ? -viewport.x : 0;
      const offsetY = viewport.y < 0 ? -viewport.y : 0;

      ctx.drawImage(
        image,
        viewport.x + offsetX, // set sx to 0 if negative
        viewport.y + offsetY, // set sy to 0 if negative
        viewport.width,
        viewport.height,
        offsetX, // shift dx if negative
        offsetY, // shift dy if negative
        this.canvasWidth,
        this.canvasHeight
      );
    }

它适用于 chrome 和 safari。

我的测试图像(400px,400px)

在此处输入图像描述

铬合金

  • 视图=(x:-100,y:-100,宽度:400,高度:400)

在此处输入图像描述

苹果浏览器

  • 视图=(x:-100,y:-100,宽度:400,高度:400)

在此处输入图像描述


推荐阅读