居然有好几个月没有更新博客了。。。我堕落了。。。 大家好,通过上一次的学习我们简单了解了非常重要的几个特性:坐标原点位移与状态保存。这两个特性对于canvas的使用有着非常多的帮助,在以后的学习中我们要渐渐接触更多与之有关的使用。同样的,在以后的
居然有好几个月没有更新博客了。。。我堕落了。。。
大家好,通过上一次的学习我们简单了解了非常重要的几个特性:坐标原点位移与状态保存。这两个特性对于canvas的使用有着非常多的帮助,在以后的学习中我们要渐渐接触更多与之有关的使用。同样的,在以后的使用中大家也会反复的使用这两个功能。所以希望大家可以多多练习,以熟练掌握它们。
今天我们来学习新的方法,首先是rotate方法,这个方法的作用是以中心为原点旋转canvas。在上次的学习中我们曾经对translate的使用进行了分析,曾经提起过以中心为原点的旋转问题,下面我们就准备来学习这个方法了。
rotate(angle)
这个方法只接受一个参数:旋转的角度(angle),它是顺时针方向的,以弧度为单位的值。
旋转的中心点始终是canvas的原点,如果要改变它,我们需要用到translate方法。
似乎很简单对吧,其实就是很简单,不用想的太过于复杂了。我们来看一个例子吧:
function draw() {
var ctx = document.getElementById('canvas').getContext('2d');
ctx.translate(75,75);
for (var i=1;i<6;i++){ // Loop through rings (from inside to out)
ctx.save();
ctx.fillStyle = 'rgb('+(51*i)+','+(255-51*i)+',255)';
for (var j=0;j<i*6;j++){ // draw individual dots
ctx.rotate(Math.PI*2/(i*6));
ctx.beginPath();
ctx.arc(0,i*12.5,5,0,Math.PI*2,true);
ctx.fill();
}
ctx.restore();
}
}
简单的说,内层循环中使用了rotate方法,以坐标中心为原点进行小圆点的绘制,外层循环中规定了离原点的绘制距离、每层的绘制个数以及颜色。也就是说,这里我们又用到了两层循环。第一层循环决定环的数量,第二层循环决定每环有多少个点。每环开始之前,都保存一下canvas的状态,这样恢复起来方便。每次画圆点,都以一定夹角来旋转canvas,而这个夹角则是由环上的圆点数目的决定的。最里层的环有6个圆点,这样,每次旋转的夹角就是360/6 = 60度。往外每一环的圆点数目是里面一环的2倍,那么每次旋转的夹角随之减半。相信这段简单的代码是难不倒大家的~
好了,我们继续下个知识点的学习,下一步我们将学习缩放。什么叫缩放不用我再讲一遍了吧,我们直接开始吧。
首先我还是来定义一下缩放的概念吧。所谓缩放。就是用来增减图形在canvas中的像素数目,对形状,位图进行缩小或者放大。
scale(x, y)
scale方法接受两个参数。x,y分别是横轴和纵轴的缩放因子,它们都必须是正值。值比1.0小表示缩小,香港服务器租用,比1.0大则表示放大,值为1.0时什么效果都没有。
默认情况下,canvas的1单位就是1个像素。举例说,如果我们设置缩放因子是0.5,1个单位就变成对应0.5个像素,这样绘制出来的形状就会是原先的一半。同理,设置为2.0时1个单位就对应变成了2像素,绘制的结果就是图形放大了2倍。
这个很简单吧,其实就是放大缩小嘛。我们借着一段代码来看一下吧:
function draw() {
var ctx = document.getElementById('canvas').getContext('2d');
ctx.strokeStyle = "#fc0";
ctx.lineWidth = 1.5;
ctx.fillRect(0,0,300,300);
// Uniform scaling
ctx.save()
ctx.translate(50,50);
drawSpirograph(ctx,22,6,5); // no scaling
ctx.translate(100,0);
ctx.scale(0.75,0.75);
drawSpirograph(ctx,22,6,5);
ctx.translate(133.333,0);
ctx.scale(0.75,0.75);
drawSpirograph(ctx,22,6,5);
ctx.restore();
// Non-uniform scaling (y direction)
ctx.strokeStyle = "#0cf";
ctx.save()
ctx.translate(50,150);
ctx.scale(1,0.75);
drawSpirograph(ctx,22,6,5);
ctx.translate(100,0);
ctx.scale(1,0.75);
drawSpirograph(ctx,22,6,5);
ctx.translate(100,0);
ctx.scale(1,0.75);
drawSpirograph(ctx,22,6,5);
ctx.restore();
// Non-uniform scaling (x direction)
ctx.strokeStyle = "#cf0";
ctx.save()
ctx.translate(50,250);
ctx.scale(0.75,1);
drawSpirograph(ctx,22,6,5);
ctx.translate(133.333,0);
ctx.scale(0.75,1);
drawSpirograph(ctx,22,6,5);
ctx.translate(177.777,0);
ctx.scale(0.75,1);
drawSpirograph(ctx,22,6,5);
ctx.restore();
}
还记得以前画了好多螺旋曲线的那个方法吗?我们又要用它啦~
这最后的例子里,我再次启用前面曾经用过的spirograph方法,来画9个图形,分别赋予不同的缩放因子。左上角的图形是未经缩放的。黄色图案从左到右应用了统一的缩放因子(x和y参数值是一致的)。看下面的代码,你可以发现,免备案空间,我在画第二第三个图案时scale了两次,中间没有restore canvas的状态,因此第三个图案的缩放因子其实是0.75 × 0.75 = 0.5625。
第二行蓝色图案堆垂直方向应用了不统一的缩放因子,每个图形x方向上的缩放因子都是1.0,意味着不缩放,而y方向缩放因子是0.75,得出来的结果是,图案被依次压扁了。原来的圆形图案变成了椭圆,如果细心观察,还可以发现在垂直方向上的线宽也减少了。
第三行的绿色图案与第二行类似,只是缩放限定在横轴方向上了。
是不是很简单呢?只要抓住诀窍就能很容易拿下这个方法了。在这个问题上我们不做过多的讲解了,让我们来到今天的高潮—变形。。。
这是最恶心也是最难的一点了,因为,你需要会图形学的基础知识。。。
你不会啊,没事,我也不会,咱一起来学~
今天所学习的最后一个方法是允许直接对变形矩阵作修改:
transform(m11, m12, m21, m22, dx, dy)
这个方法必须将当前的变形矩阵乘上下面的矩阵:
m11 m21 dx
m12 m22 dy
0 0 1
如果任意一个参数是无限大,变形矩阵也必须被标记为无限大,否则会抛出异常。
这个方法必须重置当前的变形矩阵为单位矩阵,然后以相同的参数调用transform方法。如果任意一个参数是无限大,那么变形矩阵也必须被标记为无限大,否则会抛出异常。
setTransform(m11, m12, m21, m22, dx, dy)
这个方法必须重置当前的变形矩阵为单位矩阵,然后以相同的参数调用 transform 方法。如果任意一个参数是无限大,那么变形矩阵也必须被标记为无限大,否则会抛出异常。
理解了么?不理解?好吧,让我们换个思路来看这个东西,我会尽量给大家解释清楚的。
首先是当前的变形矩阵,当前的变形矩阵是什么啊,虚拟主机,其实很简单:
x
y
1
这个就是当前的变形矩阵了。。。是不是后悔没有好好学习线代呢?
变形矩阵也就是横纵左边以及缩放倍数组成的一个矩阵,横纵坐标就是x与y,缩放倍数就是那个1。
首先让我们看一下平移:
当有:
x’=x+dx
y’=y+dy时: