资源描述:
《html5边玩边学汽车人变形》由会员上传分享,免费在线阅读,更多相关内容在应用文档-天天文库。
1、一、状态及其保存和恢复 在这一节开始之前,我们要先理解一下什么是状态以及状态的保存和恢复。玩过MFC编程的人经常能碰到这样的代码:pOldPen=pDC->SelectObject(pNewPen) 我们在选择一个新画笔对象的同时,总是要保存住旧画笔对象,为什么要这样做呢?因为新画笔对象只是临时用一下,等用完了,我们想恢复到原来的画笔配置时,如果旧的配置事先没有被保存,这些配置就丢失了,也就没办法恢复了。 在HTML5绘图中,某一刻的状态就是当前这一刻上下文对象的一系列属性的配置值,只是,决定一个画笔状态的属性比较少
2、,如颜色、粗细、线型之类的,而确定上下文状态的属性比较多,包括下面这些: 1、当前上下文对象的移动、旋转、缩放配置。 2、当前上下文对象的strokeStyle,fillStyle,globalAlpha,lineWidth,lineCap,lineJoin,miterLimit,shadowOffsetX,shadowOffsetY,shadowBlur,shadowColor,globalCompositeOperation属性值。 3、当前上下文对象的裁剪路径配置。 上面这一系列配置决定了当前这一刻上下文对象
3、的状态,其中移动、旋转、缩放、globalCompositeOperation(组合)、裁剪下面我们马上会讲到。 二、状态的保存与恢复 上面我们说某一刻的状态由那么多属性决定,我们要保存这一刻的状态就要把这些属性值一个一个都保存,恢复的时候在一个一个都设置回去,那也太麻烦了。确实是这样的,所以上下文对下提供了了两个简单的方法,对状态进行保存和恢复,他们是:save()和restore(),save和restore方法可以多次调用,每调用一次save方法,调用时的状态(即一系列属性值)就压入一个栈中。每调用一次resto
4、re方法,最后一次save的状态就被恢复,即出栈。想象一下弹匣,第一颗被发射出去的子弹,总是最后一个被压入弹匣的。 三、变型 1、移动:translate(dx,dy) 这个方法看上去很简单,其实它包含了一定的数学含义,你可以认为是整个坐标系的原点发生了移动,新坐标系下任意一点(x,y)相当于原坐标系下的坐标为: x'=x+dx y'=y+dy 如果我们调用ctx.translate(5,8)改变上下文对象的坐标系状态,然后在新状态下的点(3,2)绘图,相当于图像被绘制到了原状态下的点(8,10)处,即: x
5、'=5+3=8 y'=5+2=10 也许你会问,为什么要那么麻烦,直接在(8,10)处绘制比行吗?比如把: ctx.translate(5,8) ctx.drawImage(img,3,2) 改成: ctx.drawImage(img,8,10) 这样不是更简单、更直接吗? 我的理解是,移动更多的情况下是为其他图形变换服务的,恰当的改变坐标原点可以让图形学计算更好理解,并带来很大方便,下面我举个简单的例子,假如: 有一条线段,是x轴正向上的一小段:y=0(1<=x<=3),如果以坐标原点为圆心,逆时针旋转
6、90度,则线段与y轴正向重合,旋转后的线段为:x=0(1<=y<=3)。 但是我们不可能每次旋转都以原点为圆心进行旋转,假如我们以线段的一个端点(1,0)为圆心进行旋转,我们怎么才能得到旋转后线段上每一点的坐标值呢?其实这个过程可以分为三步: 第一步:移动原点坐标到(1,0),新的线段依然在x轴上,但是方程变为了:y=0(0<=x<=2)。 第二步:以新坐标系的原点为圆心进行旋转,得到新坐标系下的线段x=0(0<=y<=2)。 第三步:将新坐标系的原点移动到新坐标系下(-1,0)处,即将原点恢复到原来的位置,此时的
7、线段为:x= 1(0<=y<=2)。 第三步所得到的线段就是最后需要绘制的线段。 从这个例子我们可以看出来,即使在这么简单的情况下,如果不移动坐标原点来直接计算旋转后的图形,也是比较困难的。提示:当你移动坐标原点之前,千万别忘了保存状态,当然,绘制完毕后也别放了恢复状态。 2、缩放scale(sx,sy) 这个同样很简单,sx,sy是缩放比例因子,缩放后新坐标系下任意一点(x,y)相当于原坐标系下的坐标为: x'=x*sx y'=y*sy 同样,改变坐标系统总是不要忘记保存和恢复状态。 3、旋转rotate
8、(A) angle是旋转角度,旋转后新坐标系下任意一点(x,y)相当于原坐标系下的坐标为: x'=xcosA-ysinA y'=xsinA+ycosA 同样,改变坐标系统总是不要忘记保存和恢复状态。 4、变形transform(m11,m12,m21,m22,dx,dy) 其实前面讲的移动、