了解CanvasRenderingContext2D.drawImage()

    简介

    如图像压缩,没有之一。因为Canvas的很多API效果其它web技术也能实现,或者图像的像素操作等(见最后的相关资源),CanvasRenderingContext2D.drawImage()是Canvas与web结合使用最频繁的方法,那就没得选择,非使用drawImage()不可。,但是,水印合成,对于很多图像相关的处理

    语法

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

    参数

    各个参数含义和作用如下:

    image
    Object
    绘制在Canvas上的元素,可以是各类Canvas图片资源(见CanvasImageSource),如<img>图片,SVG图像,Canvas元素本身等。
    dx
    Number
    在Canvas画布上规划一片区域用来放置图片,dx就是这片区域的左上角横坐标。
    dy
    Number
    在Canvas画布上规划一片区域用来放置图片,dy就是这片区域的左上角纵坐标。
    dWidth
    Number
    在Canvas画布上规划一片区域用来放置图片,dWidth就是这片区域的宽度。
    dHeight
    Number
    在Canvas画布上规划一片区域用来放置图片,dHeight就是这片区域的高度。
    sx
    Number
    表示图片元素绘制在Canvas画布上起始横坐标。
    sy
    Number
    表示图片元素绘制在Canvas画布上起始纵坐标。
    sWidth
    Number
    表示图片元素从坐标点开始算,多大的宽度内容绘制Canvas画布上。
    sHeight
    Number
    表示图片元素从坐标点开始算,多大的高度内容绘制Canvas画布上。

    虽然看上去有9大参数,但不用慌,实际上可以就3类参数:

    1. 第1类就是image,同上,没什么好说的;
    2. 第2类就是dxdydWidthdHeight,表示在Canvas画布上划出一片区域用来放置图片,dxdy为canvas元素的左上角坐标,dWidthdHeight指Canvas元素上用在显示图片的区域大小。如果没有指定dxdydWidthdHeight这4个参数,则图片会被拉伸或缩放在这片区域内。
    3. 第3类就是sxsysWidthsHeight,你可以理解为对原始图片的提前剪裁。sxsy表示图片上sxsy这个坐标作为剪裁的左上角,sWidthsHeight尺寸范围是最终剪裁出来的图片尺寸。sxsysWidthsHeight这4个参数就可以得到一个剪裁好的新图,然后我们把这个新图放在dxdydWidthdHeight这个Canvas画布区域中,就是最终的效果。另外,此处的所有坐标和宽高值都是相对于图片的原始尺寸而言的。

    drawImage()方法有一个非常怪异的地方,大家一定要注意,那就是5参数和9参数用法的参数位置是不一样的,这个和一般的API有所不同。一般API可选参数是放在后面。但是,这里的drawImage()使用9个参数时候,可选参数sxsysWidthsHeight是在前面的。如果不注意这一点,有些表现会让你无法理解。

    下图为MDN上原理示意:
    Canvas drawimage()原理示意

    案例

    下面所有案例使用的图片资源都是下面这一张图,尺寸为500*333。

    示例图片

    1. 保持原始图片尺寸和比例

    使用context.drawImage(image, dx, dy)绘制图片,可以保持图片的原始尺寸和比例。

    例如:

    context.drawImage(image, 0, 0);

    结果效果如下:

    从实际开发经验来看,当图片的原始尺寸和我们的Canvas画布尺寸一模一样的时候,可以直接只使用imagedxdy这3个参数。

    2. 拉伸图片到指定大小和位置

    我们还可以指定Canvas中呈现图片的区域,这个时候,如果我们没有指定图片呈现的位置和尺寸的话,图片会被自动拉伸到这个指定区域内,很可能最终呈现的长宽比和原始图片就不一样。

    例如:

    context.drawImage(image, 0, 0, 300, 150);

    结果效果如下:

    可以看到图片虽然看到了全貌,但是被压扁了,不是原始的图片比例,这并不是我们需要的效果,需要进一步调整。

    3. 拉伸图片同时保持图片比例

    如何填满Canvas画布,同时保持图片的原始比例呢?这个就需要用到sxsysWidthsHeight这几个参数,注意,这4个参数是要写在dxdydWidthdHeight前面的,和一般的API不一样。

    例如:

    context.drawImage(image, 0, 42, 500, 250, 0, 0, 300, 150);

    结果效果如下:

    此案例关键是理解0, 42, 500, 250这4个坐标是怎么来的。我们最终图片要显示在300*150大小的Canvas画布中,比例是2:1,因此,我们最终设置的用来绘制的图片尺寸比例也是2:1。原始图片宽度是500,要保持2:1,则高度我们就设置为250;而原始高度是333,我们希望显示图片中心区域,因此起始垂直坐标计算下,(333 - 250) / 2,四舍五入就是42,因此,就有了对原始图片的剪裁坐标值和尺寸值0, 42, 500, 250

    其他

    规范文档

    规范地址 规范状态 备注
    HTML现行标准
    这个规范中定义了'CanvasRenderingContext2D.drawImage'
    现行标准 -

    相关资源

    兼容性

    基本功能IE9+支持,全兼容。SVG图像绘制,兼容性存疑。


    by zhangxinxu 2018-10-15 23:54:33