阅读 234

canvas绘制图像的两种缩放模式

在日常开发需求中经常会碰到canvas 画图生成海报图,其中最常见的绘制元素就是图像。一般来说呈现图像的方式都是经过缩放的(下面两种缩放模式参考微信小程序的image组件的呈现方式)。

aspectFIt

缩放模式,保持纵横比缩放图片,使图片的长边能完全显示出来。也就是说,可以完整地将图片显示出来。

图解

1.png

aspectFill

缩放模式,保持纵横比缩放图片,只保证图片的短边能完全显示出来。也就是说,图片通常只在水平或垂直方向是完整的,另一个方向将会发生截取。

图解

2.png

实现方式

canvas.drawImage用来在画布上绘制图像,他可以有以下几种方式调用:

context.drawImage(img,dx,dy,dw,dh);
context.drawImage(img,sx,sy,sw,sh,dx,dy,dw,dh);
复制代码

参数值

参数描述
img要绘制的图像
sx裁剪框右上角的x坐标
sy裁剪框右上角的y坐标
sw裁剪框的宽度
sh裁剪框的高度
dx要绘制到画布中的左上角的x坐标
dy要绘制到画布中的左上角的y坐标
dw要绘制到画布中的宽度
dh要绘制到画布中的高度

了解了上述几个参数的含义之后我们就可以开始来绘制图像了!

  • aspectFIt

    可以看到下图黑色图像想要在灰色的画布尺寸中保持纵横比显示,就需要令dh等于画布中指定的图像尺寸高度(canvasHeight),dw则等于dh * 图像的纵横比(imageWidth/imageHeight),dy显而易见是0,dx则等于(canvasWidth - dw)/2。

3.png

代码实现:

const aspectFit = (imageWidth, imageHeight, canvasWidth, canvasHeight) => {
  const imageRate = imageWidth / imageHeight
  const canvasRate = canvasWidth / canvasHeight
  let [dx, dy, dw, dh] = []
  if (imageRate >= canvasRate) {
    dw = canvasWidth
    dh = canvasWidth / imageRate
  } else {
    dh = canvasHeight
    dw = canvasHeight * imageRate
  }
  dx = (canvasWidth - dw) / 2
  dy = (canvasHeight - dh) / 2
  return [dx, dy, dw, dh]
}
复制代码
  • aspectFill

    因为canvas.drawImage可以裁剪图片至指定大小绘制到画布中,因此可以令图片在纵横比不变的情况下按照画布中规定的尺寸裁剪掉长边多余的部分。如下图所示令sh等于图像的真实高度(imageHeight),sw等于sh * 画布中规定的图像显示尺寸纵横比(canvasWdith / canvasHeight),sy显而易见是0,sx则等于(imageWidth - sw) / 2。

4.png

代码实现:

const aspectFill = (imageWidth, imageHeight, canvasWidth, canvasHeight) => {
  const imageRate = imageWidth / imageHeight
  const canvasRate = canvasWidth / canvasHeight
  let [sx, sy, sw, sh] = []
  if (imageRate >= canvasRate) {
    sw = imageHeight * canvasRate
    sh = imageHeight
    sx = (imageWidth - sw) / 2
    sy = 0
  } else {
    sh = imageWidth / canvasRate
    sw = imageWidth
    sx = 0
    sy = (imageHeight - sh) / 2
  }
  return [sx, sy, sw, sh]
}
复制代码
文章分类
前端
文章标签