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 | 目标绘制尺寸 |
| 类型 | 说明 |
|---|---|
| HTMLImageElement | img元素或new Image() |
| HTMLVideoElement | video元素 |
| HTMLCanvasElement | canvas元素 |
| 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)
const img = document.getElementById('myImage')
if (img.complete) {
ctx.drawImage(img, 0, 0)
} else {
img.onload = function() {
ctx.drawImage(img, 0, 0)
}
}
const sourceCanvas = document.getElementById('sourceCanvas')
ctx.drawImage(sourceCanvas, 0, 0)
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缓存。