HTML5 Canvas DrawImage Safari 12.0 错误(在 iOS 12.1/Mac OS Mojave 上测试)

Posted

技术标签:

【中文标题】HTML5 Canvas DrawImage Safari 12.0 错误(在 iOS 12.1/Mac OS Mojave 上测试)【英文标题】:HTML5 Canvas DrawImage Safari 12.0 bug (tested on iOS 12.1/Mac OS Mojave) 【发布时间】:2019-04-27 10:48:06 【问题描述】:

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

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

sxsy 参数应该是源的子矩形的左上角x-axisy-axis 坐标图像,以绘制到目标上下文中。 (来源:Mozilla)在 Safari 浏览器上提供的值小于 0(负值)时会有所不同。

sxsy 的负值在其他浏览器(经过测试的 Chrome 和 Microsoft Edge)上按预期工作,方法是将提到的左上角沿负边重新定位x-axisy-axis


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

这是附加的画布演示 sn-p 在 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"  ></canvas>
<div style="display:none;">
  <img id="source" src="https://i.stack.imgur.com/NS35G.jpg">
</div>

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

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

【问题讨论】:

Cropping with drawImage not working in Safari的可能重复 凯多,不,不是。源宽度和源高度不超过实际图像的宽度或高度。 @Kaiido 另外,它没有回答我的问题。我需要这种特定行为(画布顶部和左侧的空白区域),这似乎适用于除 Safari 之外的所有浏览器。您应该删除这个可能的重复标志。 @saibbyweb 这与 Safari 的 drawImage 实现中的老错误相同。好的,您不会从与建议的欺骗相同的角度来看待它,但根本原因是完全相同的,解决方案也是如此:自己计算您需要的偏移量,以便您的源矩形完全在源图像中(即没有负 x 或 y 值)。在您的情况下,它将是ctx.drawImage(image, 0, 0, 260, 130, 40, 160, 260, 130);。所以你是对的,你的源矩形不比源图像大,但正如在建议的欺骗中一样,它在外部并且正在选择不存在的像素。 这就是解决问题的方法。谢谢。标记为重复的问题并不能完全解决与我相同的问题。您在那里提到,由于某些特定标准,渲染失败,这显然不是这里的情况。我的source height and width image height and image width + 你还声称...Safari has a bug where when you try to draw non-existent pixels (out of the boundaries or the source image), it will just fail. 不,除非sxsy 的值为负数,否则它不会失败。对于正值来说很好。 【参考方案1】:

这是我经历过的。

我的代码是基于 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)

vieport=(x:-100,y:-100,宽度:400,高度:400)

野生动物园

vieport=(x:-100,y:-100,宽度:400,高度:400)

【讨论】:

以上是关于HTML5 Canvas DrawImage Safari 12.0 错误(在 iOS 12.1/Mac OS Mojave 上测试)的主要内容,如果未能解决你的问题,请参考以下文章

为啥HTML5canvas中drawImage()第一次加载只出现最后一个图,刷新就出现问题?

HTML5 Canvas drawImage 比例bug iOS

canvas的drawImage()方法,图片不显示。

来自视频的 HTML5 Canvas drawImage 在第一次绘制时未显示

HTML5 Canvas DrawImage Safari 12.0 错误(在 iOS 12.1/Mac OS Mojave 上测试)

HTML5中如何设置画布canvas中用drawImage画出来的每个图片不同的透明度?