绘制复杂图形必不可少的方法
- save() 保存 canvas 状态
- restore() 恢复 canvas 状态
Canvas 的状态就是当前画面应用的所有样式和变形的一个快照。
Canvas 的状态是以堆(stack)的方式保存的,每一次调用 save
方法,当前的状态就会被推入堆中保存起来。
实例:
1 function draw() {
2 var ctx = document.getElementById('canvas').getContext('2d');
3
4 ctx.fillRect(0,0,150,150); // Draw a rectangle with default settings
5 ctx.save(); // Save the default state
6
7 ctx.fillStyle = '#09F' // Make changes to the settings
8 ctx.fillRect(15,15,120,120); // Draw a rectangle with new settings
9
10 ctx.save(); // Save the current state
11 ctx.fillStyle = '#FFF' // Make changes to the settings
12 ctx.globalAlpha = 0.5;
13 ctx.fillRect(30,30,90,90); // Draw a rectangle with new settings
14
15 ctx.restore(); // Restore previous state
16 ctx.fillRect(45,45,60,60); // Draw a rectangle with restored settings
17
18 ctx.restore(); // Restore original state
19 ctx.fillRect(60,60,30,30); // Draw a rectangle with restored settings
20 }
移动 Translating
translate(x, y)
x 是左右偏移量,y 是上下偏移量
实例:调用 drawSpirograph
方法 9 次,用了 2 层循环。每一次循环,先移动 canvas ,画螺旋图案,然后恢复到原始状态。
1 function draw() {
2 var ctx = document.getElementById('canvas').getContext('2d');
3 ctx.fillRect(0,0,300,300);
4 for (var i=0;i<3;i++) {
5 for (var j=0;j<3;j++) {
6 ctx.save();
7 ctx.strokeStyle = "#9CFF00";
8 ctx.translate(50+j*100,50+i*100);
9 drawSpirograph(ctx,20*(j+2)/(j+1),-8*(i+3)/(i+1),10);
10 ctx.restore();
11 }
12 }
13 }
14 function drawSpirograph(ctx,R,r,O){
15 var x1 = R-O;
16 var y1 = 0;
17 var i = 1;
18 ctx.beginPath();
19 ctx.moveTo(x1,y1);
20 do {
21 if (i>20000) break;
22 var x2 = (R+r)*Math.cos(i*Math.PI/72) - (r+O)*Math.cos(((R+r)/r)*(i*Math.PI/72))
23 var y2 = (R+r)*Math.sin(i*Math.PI/72) - (r+O)*Math.sin(((R+r)/r)*(i*Math.PI/72))
24 ctx.lineTo(x2,y2);
25 x1 = x2;
26 y1 = y2;
27 i++;
28 } while (x2 != R-O && y2 != 0 );
29 ctx.stroke();
30 }
旋转 Rotating
rotate(angle) 旋转的角度(angle),它是顺时针方向的。
旋转的中心点始终是 canvas 的原点,如果要改变它,我们需要用到 translate
方法。
- 角度转弧度: π/180×角度
- 弧度变角度: 180/π×弧度
实例:
1 function draw() {
2 var ctx = document.getElementById('canvas').getContext('2d');
3 ctx.translate(75,75);
4
5 for (var i=1;i<6;i++){ // Loop through rings (from inside to out)
6 ctx.save();
7 ctx.fillStyle = 'rgb('+(51*i)+','+(255-51*i)+',255)';
8
9 for (var j=0;j<i*6;j++){ // draw individual dots
10 ctx.rotate(Math.PI*2/(i*6));
11 ctx.beginPath();
12 ctx.arc(0,i*12.5,5,0,Math.PI*2,true);
13 ctx.fill();
14 }
15
16 ctx.restore();
17 }
18 }
缩放 Scaling
- scale(x, y) 增减图形在 canvas 中的像素数目,对形状,位图进行缩小或者放大。
x,y 分别是横轴和纵轴的缩放因子,它们都必须是正值。值比 1.0 小表示缩小,比 1.0 大则表示放大,值为 1.0 时什么效果都没有。
变形 Transforms
- transform(m11, m12, m21, m22, dx, dy)
- setTransform(m11, m12, m21, m22, dx, dy)
这个方法必须重置当前的变形矩阵为单位矩阵,然后以相同的参数调用 transform
方法。如果任意一个参数是无限大,那么变形矩阵也必须被标记为无限大,否则会抛出异常。
实例:
1 function draw() {
2 var canvas = document.getElementById("canvas");
3 var ctx = canvas.getContext("2d");
4
5 var sin = Math.sin(Math.PI/6);
6 var cos = Math.cos(Math.PI/6);
7 ctx.translate(200, 200);
8 var c = 0;
9 for (var i=0; i <= 12; i++) {
10 c = Math.floor(255 / 12 * i);
11 ctx.fillStyle = "rgb(" + c + "," + c + "," + c + ")";
12 ctx.fillRect(0, 0, 100, 10);
13 ctx.transform(cos, sin, -sin, cos, 0, 0);
14 }
15
16 ctx.setTransform(-1, 0, 0, 1, 200, 200);
17 ctx.fillStyle = "rgba(255, 128, 255, 0.5)";
18 ctx.fillRect(0, 50, 100, 100);
19 }