1、保存与恢复canvas状态
ctx.save();暂时将当前的状态保存到堆中
ctx.restore();该方法用于将上一个保存的状态从堆中再次取出,恢复该状态的所有设置。
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset="utf-8">
5 <title></title>
6 <style type="text/css">
7 *{padding: 0;margin:0;}
8 body{background: #1b1b1b;}
9 #div1{margin:50px auto; width:300px; height: 300px;}
10 canvas{background: #fff;}
11 </style>
12 <script type="text/javascript">
13 window.onload = function(){
14 var c = document.getElementById('myCanvas');
15 var context = c.getContext('2d');
16
17 //开始绘制矩形
18 context.fillStyle = '#f0f';
19 context.strokeStyle = 'blue';
20 context.fillRect(20,20,100,100);
21 context.strokeRect(20,20,100,100);
22 context.fill();
23 context.stroke();
24
25 //保存当前canvas状态
26 context.save();
27
28 //绘制另外一个矩形
29 context.fillStyle = '#f00';
30 context.strokeStyle = 'green';
31 context.fillRect(140,20,100,100);
32 context.strokeRect(140,20,100,100);
33 context.fill();
34 context.stroke();
35
36 //恢复第一个矩形的状态
37 context.restore();
38
39 //绘制两个矩形
40 context.fillRect(20,140,50,50);
41 context.strokeRect(80,140,50,50);
42
43 };
44 </script>
45 </head>
46 <body>
47 <div id="div1">
48 <canvas id="myCanvas" width="300" height="200"></canvas>
49 </div>
50 </body>
51 </html>
效果展示:
2、移动坐标空间
context.translate(dx,dy); dx,dy分别表示坐标原点沿水平和垂直两个方向的偏移量。(在图形变换之前,最好使用save()方法保存当前状态的好习惯。使用restore()方法恢复原来的状态)。
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset="utf-8">
5 <title></title>
6 <style type="text/css">
7 *{padding: 0;margin:0;}
8 body{background: #1b1b1b;}
9 #div1{margin:50px auto; width:300px; height: 300px;}
10 canvas{background: #fff;}
11 </style>
12 <script type="text/javascript">
13 window.onload = function(){
14 draw();
15 };
16 function drawTop(ctx,fillStyle){
17 ctx.fillStyle = fillStyle;
18 ctx.beginPath();
19 ctx.arc(0,0,30,0,Math.PI,true);
20 ctx.closePath();
21 ctx.fill();
22 }
23
24 function drawGrip(ctx){
25 ctx.save();
26 ctx.fillStyle = 'blue';
27 ctx.fillRect(-1.5,0,1.5,40);
28 ctx.beginPath();
29 ctx.arc(-5,40,4,Math.PI,Math.PI*2,true);
30 ctx.stroke();
31 ctx.closePath();
32 ctx.restore();
33 }
34
35 function draw(){
36
37 var ctx = document.getElementById('myCanvas').getContext('2d');
38 ctx.translate(80,80);
39
40 for(var i=0; i<10; i++){
41 ctx.save();
42 ctx.translate(60*i,0);
43 drawTop(ctx,'rgb('+(30*i)+','+(255-30*i)+',255)');
44 drawGrip(ctx);
45 ctx.restore();
46 }
47
48 }
49 </script>
50 </head>
51 <body>
52 <div id="div1">
53 <canvas id="myCanvas" width="700" height="300"></canvas>
54 </div>
55 </body>
56 </html>
效果展示:
3、旋转坐标空间
context.rotate(angle); 该方法只有一个参数 旋转角度angle,旋转角度以顺时针方向为正方向,以弧度为单位,旋转中心为canvas的原点。
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset="utf-8">
5 <title></title>
6 <style type="text/css">
7 *{padding: 0;margin:0;}
8 body{background: #1b1b1b;}
9 #div1{margin:50px auto; width:300px; height: 300px;}
10 canvas{background: #fff;}
11 </style>
12 <script type="text/javascript">
13 window.onload = function(){
14 draw();
15 };
16 function drawTop(ctx,fillStyle){
17 ctx.fillStyle = fillStyle;
18 ctx.beginPath();
19 ctx.arc(0,0,30,0,Math.PI,true);
20 ctx.closePath();
21 ctx.fill();
22 }
23 function drawGrip(ctx){
24 ctx.save();
25 ctx.fillStyle = 'blue';
26 ctx.fillRect(-1.5,0,1.5,40);
27 ctx.beginPath();
28 ctx.strokeStyle = 'blue';
29 ctx.arc(-5,40,4,Math.PI,Math.PI*2,true);
30 ctx.stroke();
31 ctx.closePath();
32 ctx.restore();
33 }
34 function draw(){
35 var c = document.getElementById('myCanvas');
36 var ctx = c.getContext('2d');
37 ctx.translate(150,150);
38
39 for(var i=0; i<8; i++){
40 ctx.save();
41 ctx.rotate(Math.PI*(2/4+i/4));
42 ctx.translate(0,-100);
43 drawTop(ctx,'rgb('+(30*i)+','+(255-30*i)+',255)');
44 drawGrip(ctx);
45 ctx.restore();
46 }
47 }
48 </script>
49 </head>
50 <body>
51 <div id="div1">
52 <canvas id="myCanvas" width="300" height="300"></canvas>
53 </div>
54 </body>
55 </html>
效果展示:
4、缩放图形
ctx.scale(x,y); 其中x为x轴的缩放,y为y轴的缩放,如果要缩小,值为小于1的数值,如果要放大,值为大于1的数值。
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset="utf-8">
5 <title></title>
6 <style type="text/css">
7 *{padding: 0;margin:0;}
8 body{background: #1b1b1b;}
9 #div1{margin:50px auto; width:300px; height: 300px;}
10 canvas{background: #fff;}
11 </style>
12 <script type="text/javascript">
13 window.onload = function(){
14 draw();
15 };
16
17 function draw(){
18 var c = document.getElementById('myCanvas');
19 var ctx = c.getContext('2d');
20 ctx.translate(180,20);
21
22 for(var i=0; i<80; i++){
23 ctx.save();
24 ctx.translate(30,30);
25 ctx.scale(0.95,0.95);
26 ctx.rotate(Math.PI/12);
27 ctx.beginPath();
28 ctx.fillStyle = 'red';
29 ctx.globalAlpha = '0.4';
30 ctx.arc(0,0,50,0,Math.PI*2,true);
31 ctx.closePath();
32 ctx.fill();
33 }
34 }
35 </script>
36 </head>
37 <body>
38 <div id="div1">
39 <canvas id="myCanvas" width="300" height="300"></canvas>
40 </div>
41 </body>
42 </html>
效果展示:
5、矩阵变换
transform方法用于直接对变形矩阵作修改,即进行矩阵变形。
context.transform(m11,m12,m21,m22,dx,dy); 该方法必须将当前的变换矩阵与下面的矩阵进行乘法运算。
即:
m11(默认为1) | m21(默认为0) | dx |
m12(默认为0) | m22(默认为1) | dy |
0 | 0 | 1 |
也就是说假设A(x,y)要变换成B(x’,y’)可以通过乘以上述矩阵即可得到。
一:平移(translate), translate可以用下面的方法替代
如上图所示:
x’=x+dx
y’=y+dy
即:
其中dx为原点沿着x轴移动的数值,y为原点沿着y轴移动的数值。
context.translate(x,y)可以用下面的transform方法来替代:
context.transform(0,1,1,0,dx,dy); 或 context.transform(1,0,0,1,dx,dy);
二、缩放: scale(x,y)
x’=m11*x
y’=m22*y
或
x'=m12*x
y'=m21*y
(其中,m11、m22 和m12、m21分别表示在x轴和y轴上的缩放倍数)
则:scale(x,y); 可以通过下面的transform发放来替代:
context.transform(m11,0,0,m22,0,0); 或 context.transform(0,m12,m21,0,0,0);
三、旋转: rotate(angle);
可以用下面的transform方法来替代:
context.transform(cosΘ,sinΘ,-sinΘ,cosΘ,0,0);
其中Θ为旋转的角度,dx,dy都为0表示坐标原点不变。
如图:x' = x*cosΘ - y*sinΘ
y' = x*sinΘ + y*cosΘ
也即是
则:
context.transform(Math.cos(θ*Math.PI/180),Math.sin(θ*Math.PI/180),
-Math.sin(θ*Math.PI/180),Math.cos(θ*Math.PI/180),0,0)可以替代context.rotate(θ)。
也可以使用
context.transform(-Math.sin(θ*Math.PI/180),Math.cos(θ*Math.PI/180),
Math.cos(θ*Math.PI/180),Math.sin(θ*Math.PI/180), 0,0)替代。
eg: context.transform(0.95,0,0,0.95,30,30); 可以替代 context.translate(30,30); context.scale(0.95.0.95);
setTransform方法用于将当前的变化矩阵 重置 为最初的矩阵,然后以相同的参数调用transform方法,即先set(重置),再transform(变换)
用法: context.setTransform(m11,m12,m21,m22,dx,dy);
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset="utf-8">
5 <title></title>
6 <style type="text/css">
7 *{padding: 0;margin:0;}
8 body{background: #1b1b1b;}
9 #div1{margin:50px auto; width:300px; height: 300px;}
10 canvas{background: #fff;}
11 </style>
12 <script type="text/javascript">
13 window.onload = function(){
14 draw();
15 };
16
17 function draw(){
18 var c = document.getElementById('myCanvas');
19 var ctx = c.getContext('2d');
20 ctx.translate(200,20);
21
22 for(var i=0; i<80; i++){
23 ctx.save();
24 ctx.transform(0.95,0,0,0.95,30,30);
25 ctx.rotate(Math.PI/12);
26 ctx.beginPath();
27 ctx.fillStyle = 'red';
28 ctx.globalAlpha = '0.4';
29 ctx.arc(0,0,50,0,Math.PI*2,true);
30 ctx.closePath();
31 ctx.fill();
32 }
33
34 ctx.setTransform(1,0,0,1,10,10); //将前面的矩阵恢复为最初的矩阵,即恢复最初的原点,然后将坐标原点改为(10,10),并以新的坐标绘制一个蓝色的矩形
35 ctx.fillStyle = 'blue';
36 ctx.fillRect(0,0,50,50);
37 ctx.fill();
38
39 }
40 </script>
41 </head>
42 <body>
43 <div id="div1">
44 <canvas id="myCanvas" width="700" height="300"></canvas>
45 </div>
46 </body>
47 </html>
效果显示: