前言
在阅读完 canvas - 基础了解 后,想必大家对 canvas 有了一定的认知,那么接下来,咱们就玩点稍微有意思的东西....
绘制图像
- drawImage(image,x,y): 将独立的图片绘制在画布中(注意: 图片加载完毕后才能使用canvas进行绘制)
- 参数x, y:canvas上的坐标
- 保证图片加载完成
image = new Image();
image.src = "图片地址";
image.onload = function(){
context.drawImage(image,0,0);
}
-
drawImage(image,x,y,width,height):
- width, height: 是设置引入图片的高度和宽度,对图片进行缩放处理
- 如果不传 width、height 参数,按图片原始大小画在canvas上,超出部分被自动裁剪
-
drawImage(image,sx,sy,sw,sh,dx,dy,dw,dh);
- 规定要使用的图像
- (可选)图片-开始剪切的 x 坐标位置,
- (可选)图片-开始剪切的 y 坐标位置,
- (可选)图片-被剪切图像的宽度。
- (可选)图片-被剪切图像的高度,
- 在画布上放置图像的 x 坐标位置,
- 在画布上放置图像的 y 坐标位置,
- (可选,伸展或缩小图像)要使用的图像的宽度,
- (可选,伸展或缩小图像)要使用的图像的高度
图像平铺
-
createPattern(image,type): 并不表示绘制图片,要设置图片是否平铺,还需要用绘制方法进行单独绘制
-
参数type:表示是否平铺
- no-repeat(没意义,不平铺,我直接用drawImage,它不香么... )
- repeat
- repeat-x
- repeat-y
var image = new Image();
image.src = '1.png';
image.onload = function () {
var rpt = ctx.createPattern(image, 'repeat');
ctx.fillStyle = rpt;
ctx.fillRect(0, 0, drawing.width, drawing.height);
};
裁剪图像
- 载入图像: drawImage()或createPattern()
- 切割: clip() - 从原始画布剪切任意形状和尺寸的区域
- 注意:一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内(不能访问画布上的其他区域)。您也可以在使用 clip() 方法前通过使用 save() 方法对当前画布区域进行保存,并在以后的任意时间对其进行恢复(通过 restore() 方法)
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
// Draw a rectangle
ctx.rect(50,20,200,120);
ctx.stroke();
// Draw red rectangle
ctx.fillStyle="green";
ctx.fillRect(0,0,150,100);
// 使用 clip
var c=document.getElementById("myCanvas2");
var ctx=c.getContext("2d");
// Clip a rectangular area
ctx.rect(50,20,200,120);
ctx.stroke();
ctx.clip();
// Draw red rectangle after clip()
ctx.fillStyle="green";
ctx.fillRect(0,0,150,100);
离屏 canvas
- 多个canvas存在时,可以将第二个canvas中的内容加载到第一个canvas上
- ctx.drawImage(otherCanvas, x, y);
应用
- 水印: 为图片增加增加一个水印(在后面的 demo 中,会详细讲解水印的编码实现)
- 为水印单独设置一个 canvas2
- 然后使用 ctx1.drawImage(canvas2,x,y)-xy表示c2在c1上的位置
- 放大镜: 为一个图片增加放大镜效果(在后面的 demo 中,会详细讲解放大镜的编码实现)
像素处理
获取图像像素
-
imageDate = context.getImageData(x,y,w,h);
-
imageDate对象:矩形区域的图像数据
- width、height、data,其中data为图像信息,一维数组
- width、height、data,其中data为图像信息,一维数组
-
R - 红色 (0-255)
-
G - 绿色 (0-255)
-
B - 蓝色 (0-255)
-
A - alpha 通道 (0-255; 0 是透明的,255 是完全可见的)
将图像信息放回到 canvas 中
- context.putImageData(imageData,dx,dy,dirtyX,dirtyY,dirtyW,dirtyH)
- imageData 图像信息 一维数组
- dx、dy 将imageData放在画布中的位置
- dirtyX,如果设置值了,它会累加到dx上
- dirtyY,如果设置值了,它会累加到dy上
创建imageData
- 创建矩形图像
- context.createImageData(w,h)
举个 🌰
- 创建一个矩形图像,第一个像素变为红色,第二个像素变为绿色,其他为浅绿色
var c = document.getElementById('myCanvas');
var ctx = c.getContext('2d');
var imgData = ctx.createImageData(100, 100);
// 第一个像素变为红色
imgData.data[0] = 255;
imgData.data[1] = 0;
imgData.data[2] = 0;
imgData.data[3] = 255;
// 第二个像素变为绿色
imgData.data[4] = 0;
imgData.data[5] = 255;
imgData.data[6] = 0;
imgData.data[7] = 255;
for (var i = 8; i < imgData.data.length; i += 4) {
imgData.data[i + 0] = 0;
imgData.data[i + 1] = 66;
imgData.data[i + 2] = 0;
imgData.data[i + 3] = 77;
}
ctx.putImageData(imgData, 10, 10);
再举个 🌰
canvas.width = 500;
canvas.height = 500;
var imageData = ctx.createImageData(canvas.width, canvas.height);
var pixelData = imageData.data;
for (var i = 0; i < canvas.height; i++) {
for (var j = 0; j < canvas.width; j++) {
var p = i * canvas.width + j;
pixelData[4 * p + 0] = parseInt(Math.pow(Math.cos(Math.atan2(j - 250, i - 250) / 2), 2) * 255);
pixelData[4 * p + 1] = parseInt(
Math.pow(Math.cos(Math.atan2(j - 250, i - 250) / 2 - (2 * Math.acos(-1)) / 3), 2) * 255
);
pixelData[4 * p + 2] = parseInt(
Math.pow(Math.cos(Math.atan2(j - 250, i - 250) / 2 + (2 * Math.acos(-1)) / 3), 2) * 255
);
pixelData[4 * p + 3] = 255;
}
}
ctx.putImageData(imageData, 0, 0, 0, 0, canvas.width, canvas.height);
画布方法
状态方法
- save(): 保存当前Canvas设置
- restore(): 还原设置
转换方法:
- scale(宽的倍数,高的倍数): 设置放大或缩小,应放在绘制之前
- translate(x,y): 重新映射画布的原点位置(效果就是图像移动位置),应放在绘制之前
- rotate(要旋转的度数*Math.PI/180): 以画布的原点旋转图像,应放在绘制之前
- 原点在canvas的左上角