理解Canvas中的transform、setTransform函数

5 篇文章 0 订阅
1 篇文章 0 订阅

阅读原文:http://shuaihua.cc/article/html5/canvas-transform.php
先用transform坐标系变换绘制一个立方体

绘制结果

源代码

ctx.save();
ctx.translate(win_width/2-50, win_height/2-50);
// 后
ctx.save();
ctx.transform(1, -0.05, 0, 1, 0, 0);
ctx.globalAlpha = 0.3;
ctx.fillRect(0,0,100,100);
ctx.restore();
//左
ctx.save();
ctx.transform(0.3, 0.5, 0, 1, 0, 0);
ctx.globalAlpha = 0.4;
ctx.fillRect(0,0,100,100);
ctx.restore();
// 右
ctx.save();
ctx.transform(0.3, 0.5, 0, 1, 97, -20);
ctx.globalAlpha = 0.4;
ctx.fillRect(10,10,100,100);
ctx.restore();
// 前
ctx.save();
ctx.transform(1, -0.05, 0, 1, 20, 40);
ctx.globalAlpha = 0.6;
ctx.fillRect(10,10,100,100);
ctx.restore();
// 上
ctx.save();
ctx.transform(1, -0.053, 0.3, 0.48, -13, -2.6);
ctx.globalAlpha = 0.5;
ctx.fillRect(10,10,100,100);
ctx.restore();
ctx.restore();

ctx.setTransform(1,0,0,-1.5,0,win_height);
ctx.transform(1,0,0,1,0,0);
ctx.resetTransform();

ctx.translate(110, 110);
ctx.rotate(0 * Math.PI/180);
ctx.fillRect(-50,-50,100,100)

手写生成立方体的代码太繁琐了,一点一点调节参数,终于绘制好了。

还好有three.js这这么优秀的第三方库~制作3D效果轻松多了~

最近想更全面更深入的了解Canvas的绘图上下文API,在看到transform变换方法后有点迷惑,和CSS3里的transform有何不同?什么是矩阵运算?canvas中的translate和transform的关系和CSS3中的相同么?

查阅了一些国外原版API文档,对变换函数有了更深的了解,下面给你看。

  1. translate

translate是位移坐标系的零零位置,接下来绘制的所有形状都会基于该位置。比如下边这个例子:

for(var i=0;i<10;i++){
for(var k=0;k<10;k++){
//在使用translate的同时需要搭配save()和restore()方法来重置位置。
ctx.save();
//translate方法将矩形位移到特定的位置,传入参数包含x坐标和y坐标。
ctx.translate(i*getEleWidth(canvas_translate)/10, k*getEleWidth(canvas_translate)/10);
ctx.fillStyle = ‘rgba(‘+(100+k*11)+’,’+(185-i*20)+’,’+(10+i*9)+’,1)’;
ctx.fillRect(0,0,10,10);
ctx.restore();
}
}
1. rotate()

rotate用于旋转坐标系。传入的是弧度制。比如下边这个例子:

//位移到canvas画布的中间位置
ctx.translate(canvas_rotate.width/2, canvas_rotate.height/2);
for(var i=0;i<14;i++){
ctx.save();
//颜色又深入浅
ctx.fillStyle = ‘rgba(‘+i*14+’,’+i*14+’,’+i*14+’,1)’;
//旋转,注意将角度转换成弧度(角度*Math.PI/180)=弧度
ctx.rotate(i*52*Math.PI/180);
ctx.translate(i*9,0)
ctx.beginPath();
ctx.arc(0,0,i*3,0,Math.PI*2,true);
ctx.closePath();
ctx.fill();
ctx.restore();
}
2. transform()

transform的第2和第3个参数分别控制坐标系水平拉伸和垂直拉伸。

//拉伸
ctx.translate(5,10);
for(var i=0;i<14;i++){
ctx.save();
ctx.fillStyle = ‘rgba(‘+i*14+’,’+i*14+’,’+i*14+’,1)’;
//第一行垂直拉伸
ctx.transform(1,0,0.2,1,i*23,0);
ctx.beginPath();
ctx.fillRect(0,0,20,60);
ctx.closePath();
ctx.fill();
ctx.restore();
}
ctx.translate(canvas_skew.width/2-30,80);
for(var i=0;i<14;i++){
ctx.save();
ctx.fillStyle = ‘rgba(‘+i*14+’,’+i*14+’,’+i*14+’,1)’;
//第二行水平拉伸
ctx.transform(1,0.2,0,1,0,i*23);
ctx.beginPath();
ctx.fillRect(0,0,60,20);
ctx.closePath();
ctx.fill();
ctx.restore();
}
3. scale()

scale()控制坐标系的缩放,传入两个参数,第一个控制水平方向,第二个控制垂直方向,两个参数相等则等比缩放,默认参数为1,表示不缩放100%,即不缩放。

//缩放
ctx.translate(canvas_scale.width/2, canvas_scale.height/2);
for(var i=0;i<6;i++){
ctx.save();
ctx.fillStyle = ‘rgba(100+’+i*9+’,50+’+i*14+’,’+i*14+’,1)’;
ctx.scale(1+i,1+i);
ctx.beginPath();
ctx.arc(0,0,10+i*6,0,Math.PI*2,true);
ctx.closePath();
ctx.lineWidth = 2;
ctx.stroke();
ctx.restore();
}
4. transform()

transform(a,b,c,d,e,f)需要传入6个参数,下图矩阵中的0,0,1固定不变,a表示水平缩放,b表示垂直拉伸,c表示水平拉伸,d表示垂直缩放,e表示水平位移,f表示垂直位移。

总结规律就是,从矩阵来看,第一行的a,c,e分别表示水平方向上的缩放、拉伸、位移;第二行的b,d,f分别表示垂直方向上的拉伸、缩放、位移。

transform(1,0,0,1,0,0);
//上面的一行transform方法,相当于下方三行的方法
translate(0,0);
scale(1,1);
rotate(0)

  1. setTransform()与resetTransform()

setTransform(a,b,c,d,e,f)同样传入这6个参数,和transform不同之处在于,setTransform(a,b,c,d,e,f)能设置新的变换坐标系,而transform()是在当前新的坐标系进行变换。

resetTransform()函数不需要传入任何参数,他的作用是重置坐标系到画布刚创建时的样子,相当于执行了setTransform(1,0,0,1,0,0)

resetTransform方法的适用场景是:当我们在画布上执行了太多次transform()变换或者translate()、rotate()、scale()函数后,如果想将坐标系回复到一开始原点坐标在画布左上角的状态,就可以执行resetTransform()方法。

除了使用resetTransform()方法重置画布坐标系之外,也可以使用save()和restore()方法,将整个绘图上下文(不仅包含transform,translate,scale,scale变换,还有填充样式,描边样式,线条粗细等等属性恢复到前一个状态)。所以resetTransform()显得更小巧更灵活一些,也更暴力一些(直接恢复到最一开始的状态,而restore()是恢复到上一个状态)。

总结规律就是,从矩阵来看,第一行的a,c,e分别表示水平方向上的缩放、拉伸、位移;第二行的b,d,f分别表示垂直方向上的拉伸、缩放、位移。

参考资料:Transformations - Web APIs | MDN

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值