绘制图像

Canvas drawImage方法详解,掌握图像加载、绘制、跨域处理等核心技巧。drawImage是Canvas图像处理的核心方法,用于在画布上绘制图像。

基本语法

drawImage有三种调用形式:

// 原始尺寸绘制
ctx.drawImage(image, x, y)

// 缩放绘制
ctx.drawImage(image, x, y, width, height)

// 裁剪绘制
ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)

参数说明

参数说明
image图像源
x, y目标位置坐标
width, height目标尺寸
sx, sy源图像裁剪起点
sWidth, sHeight源图像裁剪尺寸
dx, dy目标位置坐标
dWidth, dHeight目标绘制尺寸

图像源类型

类型说明
HTMLImageElementimg元素或new Image()
HTMLVideoElementvideo元素
HTMLCanvasElementcanvas元素
ImageBitmap位图对象

加载并绘制图像

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

const img = new Image()
img.onload = function() {
  ctx.drawImage(img, 0, 0)
}
img.src = 'image.png'

基本绘制演示

图像绘制示例

缩放绘制

// 缩放到指定尺寸
ctx.drawImage(img, 0, 0, 200, 150)

// 保持宽高比缩放
const scale = Math.min(canvas.width / img.width, canvas.height / img.height)
const w = img.width * scale
const h = img.height * scale
ctx.drawImage(img, 0, 0, w, h)

缩放绘制演示

图像缩放绘制

裁剪绘制

// 从源图像(50, 50)位置裁剪100x100区域
// 绘制到画布(0, 0)位置,尺寸200x200
ctx.drawImage(img, 50, 50, 100, 100, 0, 0, 200, 200)

裁剪绘制演示

图像裁剪绘制

从img元素绘制

const img = document.getElementById('myImage')

if (img.complete) {
  ctx.drawImage(img, 0, 0)
} else {
  img.onload = function() {
    ctx.drawImage(img, 0, 0)
  }
}

从Canvas绘制

const sourceCanvas = document.getElementById('sourceCanvas')
ctx.drawImage(sourceCanvas, 0, 0)

从Video绘制

const video = document.querySelector('video')

function drawFrame() {
  ctx.drawImage(video, 0, 0, canvas.width, canvas.height)
  requestAnimationFrame(drawFrame)
}

video.addEventListener('play', drawFrame)

跨域处理

const img = new Image()
img.crossOrigin = 'anonymous'
img.onload = function() {
  ctx.drawImage(img, 0, 0)
}
img.src = 'https://example.com/image.png'

预加载图像

function loadImage(src) {
  return new Promise((resolve, reject) => {
    const img = new Image()
    img.crossOrigin = 'anonymous'
    img.onload = () => resolve(img)
    img.onerror = reject
    img.src = src
  })
}

async function draw() {
  const img = await loadImage('image.png')
  ctx.drawImage(img, 0, 0)
}

批量加载图像

批量绘制多个图像

注意事项

图像加载时机

必须在图像加载完成后才能绘制。

跨域限制

跨域图像需要设置crossOrigin属性,服务器也需要允许跨域。

性能考虑

大量图像绘制时考虑使用离屏Canvas缓存。