CanvasRenderingContext2D.drawImage() 是浏览器原生提供的在 canvas 上绘制图片的方法。

其有以下三种参数形式(详细用法说明及演示可见 MDN):

void ctx.drawImage(image, dx, dy);
void ctx.drawImage(image, dx, dy, dWidth, dHeight);
void ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
drawImage
drawImage 参数示意
(图片来源:MDN 采用 CC-BY-SA 2.5 授权)

兼容性说明

可惜 drawImage() 方法在支持 canvas 的不同浏览器上的表现不尽相同,具体不同表现可见下表及说明。关于对 canvas 的支持,可见 Can I use网站

参数 意义 约束
Chrome 1 Firefox 1 IE 2 Edge 2 Safari 3
sx, sy 源图像的选择区域的偏移量 任意数字 4 大于等于 0 的任意数字
sWidth, sHeight 源图像的选择区域的宽高 任意数字 4 1至原图像宽高的任意数字
dx, dy 目标canvas的选择区域的偏移量 任意数字
dWidth, dHeight 目标canvas的选择区域的宽高 任意数字

注:

  1. 在 Chrome 和 Firefox 下,最终的选择区域超出源图像的部分不会被绘制。
  2. 在 IE 和 Edge 下,最终的选择区域超出源图像的部分会用图像的边界像素来填充。
  3. Safari 7.1 额外要求 sx + sWidthsy + sHeight 不超过源图像的宽高,否则 drawImage() 函数不会绘制任何图像。(未在更高版本的 Safari 上测试)
  4. 在支持 canvas 的老版本的 Firefox 上,有着和 IE 等浏览器类似的对 sx, sy, sWidth, sHeight 的限制,在新版本中,这些限制已经被移除。

当使用了不满足条件的参数时,drawImage() 方法会在 IE, Edge 浏览器上抛出异常 SCRIPT5022: IndexSizeError;在 Safari 浏览器上不会抛出异常,但也不会在 canvas 上绘制图像。

注[1][2]示意:

drawImage示意

HTML 标准

以上我们可以看到不同浏览器对 drawImage() 方法有着不同的参数要求,那么哪个浏览器的行为才是正确的呢,谁才是符合标准的呢?

先看上文的 注1 和 注2,我们可以看到 HTML Standard 文档这么说:

When the source rectangle is outside the source image, the source rectangle must be clipped to the source image and the destination rectangle must be clipped in the same proportion.

即,当最终对源图像的选择区域超出了源图像本身时,应对源图像的选择区域和目标 canvas 的选择区域进行相应的裁减。这与 Chrome 和 Firefox 的行为是一致的,没有对超出部分进行绘制就是因为那些区域被裁减了,而 IE 和 Edge 浏览器则是不符合规范的,对被裁减部分也进行了绘制。

再看上文表格中 IE, Edge, Safari 浏览器要求 sWidth, sHeight 大于等于 1,也与 HTML 标准中的说法想矛盾。

If one of the sw or sh arguments is zero, abort these steps. Nothing is painted.

HTML 标准中显式的说明了 sWidth 和 sHeight 为零的情况是允许的,只是在这种情况下不会绘制任何图像而已。至于 sWidth 和 sHeight 为负值的情况也被涵盖在以下公式中:

The source rectangle is the rectangle whose corners are the four points (sx, sy), (sx+sw, sy), (sx+sw, sy+sh), (sx, sy+sh).

The destination rectangle is the rectangle whose corners are the four points (dx, dy), (dx+dw, dy), (dx+dw, dy+dh), (dx, dy+dh).

负值的情况也有另外被明确说明和允许:

The image data must be processed in the original direction, even if the dimensions given are negative.

通过与 HTML 标准文档的对照,不难发现 Chrome, Firefox 是更贴合 HTML 标准的现代浏览器。


扩展阅读