一、 translate
图形的位移translate(x,y)
此函数要放在图形绘制前进行调用,这有点和我们想象的不一样,之所以出现这样的现象,看看后面的效果便知道了,首先我们绘制的是没有变换的正方形,左上角的坐标是(100,100),边长是100,然后是经过横坐标增加200与纵坐标增加100变换的正方形,然后我们再绘制左上角坐标是(300,200),边长与上面绘制的正方形相同的正方形。
为了视觉效果,我将三次操作后的效果图片弄在一张图片上:

二、 rotate
图形的转换rotate(deg)
这里的deg是一个弧度制,所以需要将度数/180然后乘以Math.PI,当然直接可以传弧度制,我们试着将正方形旋转三十度(图在后面)。同样的,这个操作需要放在前面,而不是后面。
context.rotate(30/180*Math.PI);
context.strokeRect(200,100,200,200);
将旋转操作放到绘制之前。同时我有一个疑问,那就是为什么旋转角不是左上角的顶点,还有就是是不是所有的旋转都是围绕着一个点旋转(指同一图形旋转),首先我们验证第二个疑问。
以下是代码部分:
for(var i = 0; i < 180; i ++){
context.rotate(i/180*Math.PI);
if(i == 0){
context.fillStyle = "rgba(255,0,0,0.5)"
context.fillRect(400,250,100,100);
}
context.strokeRect(400,250,100,100);
}


我们发现,这些图形都围绕着坐标原点进行旋转,所以旋转30度的那个图的旋转轴不正确,应该是左上角的点与坐标原点的连线。以此我们解决了第二个问题,的确围绕着一个点在旋转。同时我们也知道第一个问题的答案,之所以发生左上角坐标的改变,是因为旋转轴的缘故,如果要实现围绕左上角的坐标点的旋转,那么需要将坐标原点移动到左上角坐标位置,所以我们得使用translation。
那接下来我就尝试实现。
首先让我们看看代码部分:
context.translate(400,250); //将坐标轴移动到我们绘制的地方
for(var i = 0; i < 180; i += 2){
context.rotate(i/180*Math.PI);
if(i == 0){
context.fillStyle = "rgba(255,0,0,0.5)"
context.fillRect(0,0,100,100);//对于填充色,我们要根据新坐标轴进行绘制
context.strokeRect(400,250,100,100);//我们是在第一次绘制的基础上进行位移
}
context.strokeRect(0,0,100,100);//在新的坐标原点绘制
}
以下是效果部分:

三、scale
图形的缩放scale(x,y)
首先将图形水平与垂直方向同时放大1.5倍,
代码部分:
context.lineWidth = 10; //设置线条的宽度为10
context.strokeRect(100,50,200,200);
context.scale(1.5,1.5);
context.strokeRect(100,50,200,200);
以下是一张两种效果叠加图:

四、 深入理解图形变换
图形变换矩阵
a c e
b d f
0 0 1
其中:
a 水平缩放
b 水平倾斜
c 垂直倾斜
d 垂直缩放
e 水平位移
f 垂直位移
图形变换中,每一个坐标都会经过图形变换矩阵,然后得到最新的值。
官方提供了函数供我们改变图形变换矩阵的a、b、c、d、e、f的值。
transform(a,b,c,d,e,f)
函数中的a、b、c、d、e、f所对应矩阵中的a、b、c、d、e、f。
如果我们需要进行位移操作,那么我们就可以改变e和f的值:transform(1,0,0,1,50,50);
当transform里面的参数是单位矩阵时,此时的图片不进行任何变换,即(1,0,0,1,0,0)。
通过变换矩阵进行图形变换仍然存在上面的那些问题,所以我们在使用图形变换函数的时候,需要时注意。
接下来介绍一对函数,
save() 用于保存当前状态;
restore()用于恢复使用save函数保存的状态。
所以一般情况下,在使用图形变换前都先使用save函数,图形变换以后再使用restore函数恢复我们最初的状态。以下是图形位移的操作,我们使用矩阵函数来操作,我打算首先将一个矩形水平位移200,垂直位移100,然后我们在绘制基于最初坐标轴绘制边长为100,左上角坐标是100,100的正方形,首先我们不使用save与restore函数。
代码部分:
context.lineWidth = 10; //设置线条的宽度为10
context.transform(1,0,0,1,200,100);
context.strokeRect(50,50,100,100);
context.fillStyle = "red";
context.fillRect(100,100,100,100);
context.strokeRect(100,100,100,100);
以下是效果部分:

我们使用save与restore函数以后的效果
代码部分:
context.lineWidth = 10; //设置线条的宽度为10
context.save();
context.transform(1,0,0,1,200,100);
context.strokeRect(50,50,100,100);
context.restore();
context.fillStyle = "red";
context.fillRect(100,100,100,100);
context.strokeRect(100,100,100,100);
效果部分,以下并没有标注坐标,但坐标参考线仍然存在:

网友评论