什么是canvas?
HTML5 元素用于图形的绘制,通过脚本 (通常是JS)来完成.
标签只是图形容器,必须使用脚本来绘制图形
浏览器支持情况
如何使用canvas?
添加canvas标签
获得canavs元素(可以理解为画布)
获得canvas上下?文对象(可以理解为画笔)
//获取canvas元素对象
var canvas = document.getElementById('canvas');
//获取上下文对象
var ctx = canvas.getContext('2d');
1
2
3
4
5
6
71
2
3
4
5
6
7
线段
1.ctx.moveTo(x, y) 将画笔移动到 x,y坐标点(当前点)
2.ctx.lineTo(x, y) 从当前点绘制直线到x,y点
3.ctx.stroke() 描边
4.ctx.lineWidth = 20 设置线段宽度
5.ctx.closePath() 闭合当前路径
6.ctx.fill() 填充
fill和stroke都是作用在当前自路径的,另外完成一条路径后要开始另一条子路径的时候必须使用beginPath()
通过上述方法就可以画一个闭合三角形了:
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.lineWidth = '10';
ctx.moveTo(100, 50);
ctx.lineTo(50, 100);
ctx.lineTo(50, 150);
ctx.closePath();
ctx.strokeStyle = 'red';
ctx.stroke();1
2
3
4
5
6
7
8
91
2
3
4
5
6
7
8
9
矩形
1.ctx.rect(x, y, dx, dy) 需要与stroke配合才能画出矩形
2.ctx.fillRect(x, y, dx, dy) 相当于ctx.rect()和fill的合集
3.ctx.strokeRect(x, y, w, h) 相当于ctx.rect()和stroke的合集
4.ctx.clearRect(x, y, dx, dy) 擦除当前区域
可以通过以上方法实现矩形下落的动画:
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var y = 100;
window.setInterval(function () {
if (y <= 400) {
ctx.clearRect(0, 0, 500, 500);
ctx.strokeRect(100, y, 100, 100);
}
y += 10;
},100);1
2
3
4
5
6
7
8
9
10
11
1
2
3
4
5
6
7
8
9
10
11
弧形
1.arc(x, y, r, 起始弧度, 结束弧度,弧形的?方向 ) 其中0表示顺时针,1表示逆时针
圆角
1.ctx.arcTo(x1, y1, x2, y2, r)
我们可以做一个圆角矩形:
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(150, 50);
ctx.arcTo(200, 50, 200, 150, 20);
ctx.arcTo(200, 150, 100, 150, 20);
ctx.arcTo(100, 150, 100, 50, 20);
ctx.arcTo(100, 50, 200, 50, 20);
ctx.closePath();
ctx.stroke();1
2
3
4
5
6
7
8
9
10
111
2
3
4
5
6
7
8
9
10
11
坐标轴转换
1.translate(dx, dy) 重新映射画布上的 (0,0) 位置
2.scale(sx, sy) 缩放当前绘图
3.rotate(Math.PI) 旋转当前的绘图
4.save() 保存当前图像状态的一份拷贝
5.restore() 从栈中弹出存储的图形状态并恢复
6.setTransform(a, b, c, d, e, f) 先重置再变换
参数:水平旋转、水平倾斜、垂直倾斜、垂直缩放、水平移动、垂直移动
7.transform(a, b, c, d, e, f) 在之前的基础上变换
填充图案
ctx.createPattern(image|canvas元素|video元素,”repeat|repeat-x|repeat-y|no-repeat”)
这个方法类似将图片以一种填充的模式给画笔
例如,用图片填满画布:
var canvas = document.getElementById('canvas');
var img = document.getElementById('img');
var ctx = canvas.getContext('2d');
//这里要注意等到img加载完成后再执行代码
img.onload = function () {
ctx.fillStyle = ctx.createPattern(img, 'repeat');
ctx.fillRect(0, 0, 500, 500);
}1
2
3
4
5
6
7
8
91
2
3
4
5
6
7
8
9
渐变
1.createLinearGradient(x1, y1, x2, y2); 创建线性渐变
2.createRadialGradient(x1, y1, r1, x2, y2, r2); 创建径向渐变
3.addColorStop(p, color) 指定颜色停止,参数是0至1.
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
// 创建线性渐变
var grd=ctx.createLinearGradient(0,0,200,0);
grd.addColorStop(0,"red");
grd.addColorStop(1,"white");
// 填充渐变
ctx.fillStyle=grd;
ctx.fillRect(10,10,150,80);1
2
3
4
5
6
7
8
9
10
111
2
3
4
5
6
7
8
9
10
11
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
// 创建径向渐变
var grd=ctx.createRadialGradient(75,50,5,90,60,100);
grd.addColorStop(0,"red");
grd.addColorStop(1,"white");
// 填充渐变
ctx.fillStyle=grd;
ctx.fillRect(10,10,150,80);1
2
3
4
5
6
7
8
9
10
111
2
3
4
5
6
7
8
9
10
11
线段样式
1.lineCap
2.lineJoin
合成
1.ctx.globalCompositeOperation = ” ;值为新像素和就像素的合并方式,一共有11种值
绘制图片
1.ctx.drawImage() 第一个参数是img(Image,canvas,video)
2.三个参数 (x, y) 起始点坐标
3.五个参数 (x, y, dx, dx) 起始点坐标及图片所存区域的宽高
4.九个参数 (x1, y1, dx1, dy1, x2, y2, w2, h2) 前四个为所绘制目标元素的起始点和宽高;后四个为canvas绘制的起始点和大小;
导出canvas
canvas.toDataURL(): canvas自身的方法不是上下文对象
1.这个方法可以将canvas抽取成一张图片,返回值是base64编码(该方法受同源策略的影响)
2.可以将返回的base64编码放入到img标签中的src中,以导出
获取canvas像素信息
ctx.getImageData(x, y, dx, dy) // 获取像素信息
ctx.createImageData(w, h) //创建新的空白 ImageData 对象
ctx.putImageData(imgData, x, y) //将图像像素数据放回画布上
我们可以通过上述代码实现将黑色矩形变为灰色:
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.fillRect(0, 0, 10, 10);
var p = ctx.getImageData(0, 0, 10, 10);
var row = p.width;
var col = p.height;
var d = p.data;
//对像素信息进行变换
for (var i = 0; i < row; i++) {
var c = i * col * 4;
for (var j = 0; j < col; j++) {
d[c + j * 4 + 3] = 100;
}
}
//将信息放回画布上
ctx.putImageData(p, 10, 10);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
191
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
命中检测
1.ctx.isPointInPath(x, y);检测是否在区域内,chrome 与safari的区别
2.ctx.isPointInStroke(x, y);检测是否在线上
还可以通过检测当前点的像素值,如果为透明,则该点不再路径上