没有前奏,直接进入主题canvas
transform调用方法:spa
ctx.transform(a,b,c,d,e,f);以下3d
var ctx = document.getElementById("myCanvas").getContext("2d"); //调用 ctx.transform(1,1,-1,1,1,1); //画个圆形的路径 ctx.arc(200,100,25,0,2*Math.PI); //画个已填充的矩形 ctx.fillRect(200,150,50,50); //对路径描边 ctx.stroke();
结果以下(只截取了主要部分):code
使用transform前 使用transform后orm
咋一看,三个变化:blog
①两个图形的位置变化了 get
②矩形的角度变化了 数学
③图形的大小变化form
这里正好反应了三个属性:位移、旋转、缩放,对应canvas的另外三个API则是translate()、rotate()、scale()。这三个API使用起来直观,可是却不能实现某些特定的效果,好比斜切。class
var canvas = document.getElementById("myCanvas"); var ctx = canvas.getContext("2d"); //Y轴逐渐拉伸,获得上图右边状态 ctx.transform(1,Math.PI/18,0,1,0,0); ctx.fillRect(200,150,50,50);
仅经过原有的三个比较直观的API并不能实现这个效果,然而或许你在别的地方看过,transform除了能够实现斜切,也能够直接替代掉原有的三个API实现它们对应的效果。
(一)位移
用transform来替代就是修改最后两个参数: ctx.transform(a,b,c,d,e,f) 其中的e和f两个参数。
(二)旋转
旋转呢,就须要配合四个参数来实现了,ctx.transform(a,b,c,d,e,f)其中的abcd四个参数(为何要四个?先别急,后面再说,总之你记住就行了)。
(三)缩放
缩放仅须要修改前两个参数便可,ctx.transform(a,b,c,d,e,f);
--------------------------------------
请记住三种状况对应的相关参数
--------------------------------------
接下来我们说说为何?
先说简单的:位移和缩放
对于坐标轴上的任意一点 A(x,y)移动到B(x1,y1),则B点的坐标值能够用以下的等式表示:
x1 = x + e
y1 = y + f
同理,对于坐标轴上的任意一点 A(x,y)缩放到B(x1,y1),则B点的坐标值能够用以下的等式表示:
x1 = x * a
y1 = y * d
其中a、d对应transform中的第一和第四个参数,位移的时候e和f表明具体的数值,而缩放的时候a和d则表明了对应x或者h轴上的缩放倍数,因此默认的倍数固然是1(也就是原来的大小),默认的位移固然是0,因此咱们如今知道transform(a,b,c,d,e,f)的参数中a,d为1,e,f为0。
接下来看比较复杂的旋转,如图:
以点(0,0)为中心,将点A(100,-100)旋转45°后求点B的坐标轴是多少?(由于在咱们的Canvas中y轴向下才是正数,因此请换位思考一下)。
若是你会解答这道题,而且能推演一个坐标随角度变化而变化的公式,那么你很对得起你的几何老师,惋惜我推不出来,我数学是挂科的!!!因此我就直接把答案搁这儿了:
x1 = x * cos(弧度) - y * sin(弧度);
y1 = y * cos(弧度) + x * sin(弧度);
弧度 = Math.PI * 180 / 角度
-------------------------------------------------------------
最终的公式
x1 = ax + cy + e
y1 = bx + dy + f
调用:
ctx.transform(cos(弧度),sin(弧度),-sin(弧度),cos(弧度),0,0);
var canvas = document.getElementById("myCanvas"); var ctx = canvas.getContext("2d"); var deg = Math.PI/180; //旋转45° ctx.transform(Math.cos(deg*45),Math.sin(deg*45),-Math.sin(deg*45),Math.cos(deg*45),0,0); ctx.fillRect(200,0,50,50);
若是我要旋转45°而且放大两倍,位移到(100,100)呢?我并无在别的地方找到答案。我觉得a和d既然是控制缩放的,那么乘以2如何?
var canvas = document.getElementById("myCanvas"); var ctx = canvas.getContext("2d"); var deg = Math.PI/180; ctx.fillRect(200,0,50,50); //第一个正方形(未变形) ctx.setTransform(1,0,0,1,0,0); ctx.beginPath(); ctx.transform(2*Math.cos(deg*45),Math.sin(deg*45),-Math.sin(deg*45),2*Math.cos(deg*45),0,0); ctx.fillRect(200,0,50,50); //第二个正方形(仅a和d乘以2) ctx.setTransform(1,0,0,1,0,0); ctx.beginPath(); ctx.transform(2*Math.cos(deg*45),2*Math.sin(deg*45),-2*Math.sin(deg*45),2*Math.cos(deg*45),0,0); ctx.fillRect(200,0,50,50); //第三个正方形(正确的解答)
你没看错,abcd四个参数所有乘以2才是正确的(对于数学不太好的我,花了四五个小时也想不通,最后斗胆一试所有乘以2竟然神奇的正确了O(∩_∩)O~~)
与下面两种方法获得相同的结果:
//第一:直接使用缩放和旋转的API ctx.scale(2,2); ctx.rotate(Math.PI/180*45); //第二:使用transform分别替换上面两种API var deg = Math.PI/180; ctx.transform(2,0,0,2,0,0); ctx.transform(Math.cos(45*deg),Math.sin(45*deg),-Math.sin(45*deg),Math.cos(45*deg),100,100);
总结: