canvas更有意思的一项特性就是图像操作能力。可以用于动态的图像合成或者作为图形的背景,以及游戏界面(Sprites)等等。浏览器支持的任意格式的外部图片都可以使用,比如PNG、GIF或者JPEG。 你甚至可以将同一个页面中其他canvas元素生成的图片作为图片源。
引入图像到canvas里需要以下两步基本操作:
- 获得一个指向HTMLImageElement的对象或者另一个canvas元素的引用作为源,也可以通过提供一个URL的方式来使用图片(参见例子)
- 使用drawImage()函数将图片绘制到画布上
一、获得需要绘制的图片
可以获取图片源的API:
方法、属性 | 描述 |
---|---|
HTMLImageElement | 这些图片是由Image()函数构造出来的,或者任何的元素 |
HTMLVideoElement | 用一个HTML的 元素作为你的图片源,可以从视频中抓取当前帧作为一个图像 |
HTMLCanvasElement | 可以使用另一个 元素作为你的图片源。 |
ImageBitmap | 这是一个高性能的位图,可以低延迟地绘制,它可以从上述的所有源以及其它几种源中生成。 |
这些源统一由 CanvasImageSource类型来引用。
1. 使用相同页面内的图片
- document.images集合
- document.getElementsByTagName()方法
- 如果你知道你想使用的指定图片的ID,你可以用document.getElementById()获得这个图片
2. 使用其它域名下的图片
在 HTMLImageElement上使用crossOrigin属性,你可以请求加载其它域名上的图片。如果图片的服务器允许跨域访问这个图片,那么你可以使用这个图片而不污染canvas,否则,使用这个图片将会污染canvas。
3. 使用其它canvas元素
和引用页面内的图片类似地,用 document.getElementsByTagName 或 document.getElementById 方法来获取其它 canvas 元素。但你引入的应该是已经准备好的 canvas。
4. 从零创建图像
var img = new Image();
img.src = "image.png" // 图片源地址
5. data: url 方式嵌入
Data urls 允许用一串 Base64 编码的字符串的方式来定义一个图片。
其优点就是图片内容即时可用,无须再到服务器兜一圈。(还有一个优点是,可以将 CSS,JavaScript,HTML 和 图片全部封装在一起,迁移起来十分方便。)缺点就是图像没法缓存,图片大的话内嵌的 url 数据会相当的长:
6. 使用视频帧
你还可以使用 中的视频帧(即便视频是不可见的)。例如,如果你有一个ID为“myvideo”的 元素,你可以这样做:
function getMyVideo() {
var canvas = document.getElementById('canvas');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
return document.getElementById('myvideo');
}
}
二、绘制图片
方法 | 描述 |
---|---|
drawImage(image, x, y) | 其中 image 是 image 或者 canvas 对象,x 和 y 是其在目标 canvas 里的起始坐标。 |
SVG图像必须在 <svg> 根指定元素的宽度和高度。
// 通过使用img图片作为背景图,减少不必要的作图。
function draw() {
var ctx = document.getElementById('canvas').getContext('2d');
var img = new Image();
img.onload = function () {
ctx.drawImage(img, 0, 0, 500, 400);
ctx.strokeStyle = 'skyblue';
ctx.lineWidth = 2;
ctx.moveTo(80, 300);
ctx.lineTo(110, 280);
ctx.lineTo(130, 250);
ctx.lineTo(170, 100);
ctx.lineTo(200, 140);
ctx.lineTo(250, 100);
ctx.lineTo(330, 280);
ctx.lineTo(400, 150);
ctx.lineTo(470, 280);
ctx.stroke();
};
img.src = 'https://mdn.mozillademos.org/files/5395/backdrop.png';
}
三、缩放
方法 | 描述 |
---|---|
drawImage(image, x, y, width, height) | 这个方法多了2个参数:width 和 height,这两个参数用来控制 当向canvas画入时应该缩放的大小。 |
function draw() {
var ctx = document.getElementById('canvas').getContext('2d');
var img = new Image();
img.onload = function () {
for (let i = 0; i < 5; i++) {
for (let j = 0; j < 5; j++) {
ctx.drawImage(img, i * 96 + 10, j * 96 + 10, 96, 96);
}
}
};
img.src = 'https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=2789413579,2948231443&fm=26&gp=0.jpg';
}
根据 drawImage() 的缩放参数实现缩放,然后再通过for循环进行行列的平铺,效果如下:
四、切片Slicing
这次的功能也仍是 drawImage() 所实现的:
方法 | 描述 |
---|---|
drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight) | 第一个参数和其它的是相同的,都是一个图像或者另一个 canvas 的引用。前4个是定义图像源的切片位置和大小,后4个则是定义切片的目标显示位置和大小。 |
function draw() {
var ctx = document.getElementById('canvas').getContext('2d');
var img = new Image(); // 犀牛
img.onload = function () {
// 前面四个参数切取的位置以及切取大小,后面四个参数设置切图后摆放的位置及尺寸。
ctx.drawImage(img, 200, 100, 100, 150, 0, 0, 200, 250);
};
img.src = 'https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=2789413579,2948231443&fm=26&gp=0.jpg';
}
- 画框(MDN案例),示例:画廊 Art gallery example
<html>
<body onload="draw();">
<canvas id="canvas" width="150" height="150"></canvas>
<div style="display:none;">
<img id="source" src="https://mdn.mozillademos.org/files/5397/rhino.jpg" width="300" height="227">
<img id="frame" src="https://mdn.mozillademos.org/files/242/Canvas_picture_frame.png" width="132" height="150">
</div>
</body>
</html>
function draw() {
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
// Draw slice
ctx.drawImage(document.getElementById('source'), 33, 71, 104, 124, 21, 20, 87, 104);
// Draw frame
ctx.drawImage(document.getElementById('frame'), 0, 0);
}
五、控制图像的缩放行为 Controlling image scaling behavior
过度缩放图像可能会导致图像模糊或像素化。您可以通过使用绘图环境的imageSmoothingEnabled属性来控制是否在缩放图像时使用平滑算法。默认值为true,即启用平滑缩放。同时也可以像这样禁用此功能:
// Gecko内核
ctx.mozImageSmoothingEnabled = false;
// WebKit内核
ctx.webkitImageSmoothingEnabled = false;
// Trident内核
ctx.msImageSmoothingEnabled = false;
// 标准
ctx.imageSmoothingEnabled = false;