何为转换功能?熟悉css3的同学都知道,css3里面有transform,translate,scale,rotate,animation等等,这就是css3的转换功能,同样,canvas也支持,但是只是支持部分,那我们来看看,都支持哪些,和css3相比,有什么区别?
1、scale
scale(scaleWidth,scaleHeight) 缩放当前绘图
参数:scaleWidth 表示缩放当前绘图的宽度,取值如0.5 = 50% ,1 = 100% , 2 = 200%以此类推 ; scaleHeight 表示缩放当前绘图的高度,取值如0.5 = 50% ,1 = 100% , 2 = 200%以此类推
我们可以先看看css3是什么表现:
css3 scale(sx,sy) sx,sy分别表示向横坐标和纵坐标的缩放向量,取值如0.5 = 50% ,1 = 100% , 2 = 200%以此类推 基本上跟canvas是一样,只是说法不一样而已,那既然用法是一样的,我们就来试一下:
ctx.strokeStyle = 'red'; ctx.strokeRect(5,5,50,50); ctx.scale(2,2); ctx.strokeRect(5,5,50,50); ctx.scale(2,2); ctx.strokeRect(5,5,50,50);
咦,你会看到一个很奇怪的现象,它不是从定位的原点开始缩放的,而是偏移了原点,实际上是不仅仅是图形缩放了,就连图形的边距也缩放了,且缩放的倍数与图形倍数一致,我们看一下css3的scale会有什么样的表现:
.box{ width:50px; height:50px; border:1px solid #000; margin:20px; } .box:hover{ -webkit-transform:scale(2,2); }
css3的表现是以图形的中心点为原点,然后向四周缩放,由此我们得到canvas 的scale与css3的scale的不同点之一;
不同点之二就是,css3的scale,如果x,y轴的缩放倍数一样的话,是可以缩写成一个参数的,如:
.box:hover{ -webkit-transform:scale(2); }
效果是一样一样的,但是canvas的2个参数即使缩放倍数一样,也是不能进行简写的,必须2个参数都写才能运行;
说到这里,我想起来在canvasAPI开篇的时候留了一个悬念,就是canvas画布的宽高设置必须在canvas标签属性上设置,而不能在css里设置,这是为什么呢?下面大家来看一个例子:
第一组,我们用css来定义canvas的宽高,标签属性上不设样式:
canvas{ background:#fff; width:300px; height:300px; }
ctx.strokeStyle = 'red'; ctx.strokeRect(5,5,50,50);
咦,这是什么鬼?
第二组,我们用canvas标签属性来设宽高,不用css设置:
<canvas width="300" height="300" id="canvas"> <span>亲,您的浏览器不支持canvas,换个浏览器试试吧!</span> </canvas>
明显是在标签属性上设置的宽高是正常的,为什么css设置宽高会出现这种诡异的状况,原因是canvas本身是有默认宽高的(宽300,高150),如果在css中设置宽高,会让canvas认为,现在canvas的宽度倍自动缩放了,缩放比例为css设置的宽度/300,高的也一样,那么就可以理解了,现在css设置的宽度是300,高的是300,那么就会缩放宽=300/300,高缩放=300/150,高的自然就被拉高了一倍,所以这才是必须在canvas的属性上设置宽高的原因
我们回到scale,我们来给给一个动态图,来看看scale的变化过程:
var timer = null; ctx.strokeStyle = 'red'; timer = setInterval(function(){ ctx.beginPath(); ctx.scale(1.5,1.5); ctx.strokeRect(5,5,50,50); ctx.closePath(); },500)
可以从这个gif图中可以看出,scale的变化是在前面的一次绘图的基础上再次缩放,然后再缩放,有人说,你这个定时器是本来就是原来的基础上再缩放一次,理所应该就是这样,但是这个效果不好看,能不能我设一个参数,然后让它累加,慢慢的缩放,且只有一个图形呢?
嗯,这里就需要解释一个方法叫clearRect(),表示在指定的范围内清除样式,这里如果需要只有一个图形,那么就必须在下一次绘制图形之前清除掉前面的一次绘图,因为中间的时间极短,就感觉是连续的,我们先介绍一下这个clearRect()方法吧:
clearRect(x,y,w,h) 参数:w,y表示需要清除的矩形的左上角坐标,w,h表示需要清除的矩形的宽高
从参数可以看出,它是可以清除局部区域的像素的,如果区域设为画布,则是清除整个画布了,好了,让我们一起来写一下你想要的那种效果:
var timer = null; var num = 1; ctx.strokeStyle = 'red'; timer = setInterval(function(){ if(parseInt(num) >=5){ clearInterval(timer); num =5; }else{ num +=0.1; } ctx.clearRect(0,0,canvas.clientWidth,canvas.clientHeight); ctx.save(); ctx.beginPath(); ctx.scale(num,num); ctx.strokeRect(5,5,50,50); ctx.closePath(); ctx.restore(); },500)
看上图,现在就可以安安静静看它是怎么缩放的了,边距和图形一起缩放,比例也是一样的,这里的效果之所以没有和上面的gif图一样,在上一次缩放的基础上缩放,是因为这一对活宝:save()和restore(),这对活宝上一篇已经讲过了,如果还是不熟悉的同学出门右转,找到API的第3篇,这里的这一对主要功能是保存当前的路径,不被其他的路径污染,这对活宝和clearRect()在做运动的时候是非常有用的,这里终点提示一下!
2、rotate
rotate(angle) 旋转当前绘图 参数:angle表示旋转角度,这里需要填写弧度(弧度和角度的关系,在前面就已经讲过了,不熟悉的同学可以找到API的第2篇)
同样我们看一下css3 rotate的表现:
.box{ width:50px; height:50px; border:1px solid #000; margin:20px; } .box:hover{ -webkit-transform:rotate(30deg); }
可以看到css3的旋转是以中心为原点进行旋转,切接受的参数直接就是角度,而不是弧度,那canvas的rotate的表现是什么呢?
ctx.fillStyle = 'red'; ctx.fillRect(0,0,150,50); ctx.beginPath(); ctx.rotate(30*Math.PI/180); ctx.strokeRect(0,0,150,50); ctx.closePath();
红色为初始图形,黑色为旋转图形,这是将图形坐标设置画布左上角的地方的
ctx.fillStyle = 'red'; ctx.fillRect(50,50,150,50); ctx.beginPath(); ctx.rotate(30*Math.PI/180); ctx.strokeRect(50,50,150,50); ctx.closePath();
图形坐标设置50,50处
ctx.fillStyle = 'red'; ctx.fillRect(100,100,150,50); ctx.beginPath(); ctx.rotate(30*Math.PI/180); ctx.strokeRect(100,100,150,50); ctx.closePath();
图形坐标设在100,100处
从这个3组效果中,我们可以得出这样的结论:
1、canvas的旋转原点并不是以自身的中心为原点,而是以画布的左上角为原点,3张图的比较可以看出来
2、图形的旋转原点也不是其自身的中心,而是其左上角为原点
这里说了2个原点,可能不好理解哈,几个例子,比如地球,它即绕太阳转,自己本身也转,那么它让太阳转就是我们说的第一点,图形绕画布旋转,准确的来说,也是图形的左上角绕画布左上角旋转,太阳的自转就是我们说的第2点,它自己本身的旋转,只不过canvas图形中的自转不是以中心为原点的旋转,其中心在左上角,这应该就明白看吧!
3、translate
translate(x,y) 重新映射画布上的 (0,0) 位置,这怎么理解?通俗的将,就是重新定义坐标原点,默认原点是(0,0),用此方法会将原点