深入解析HTML5 Canvas控制图形矩阵变换的方法


Posted in HTML / CSS onMarch 24, 2016

在介绍矩阵变换transform()前,我们来说一说什么是变换矩阵。
深入解析HTML5 Canvas控制图形矩阵变换的方法

以上是Canvas中transform()方法所对应的变换矩阵。而此方法正是传入图中所示的六个参数,具体为context.transform(a,b,c,d,e,f)。

各参数意义对应如下表:

参数 意义
a 水平缩放(1)
b 水平倾斜(0)
c 垂直倾斜(0)
d 垂直缩放(1)
e 水平位移(0)
f 垂直位移(0)

当我们把对应的0或1代入进矩阵,可以发现这是一个单位矩阵(水平和垂直缩放默认值是1,代表缩放1倍,即不缩放)。该方法使用一个新的变化矩阵与当前变换矩阵进行乘法运算,然后得到各种变化的效果。

这里简单说一下,当我们想对一个图形进行变换的时候,只要对变换矩阵相应的参数进行操作,操作之后,对图形的各个定点的坐标分别乘以这个矩阵,就能得到新的定点的坐标。

transform()方法

而Canvas绘图中,就给咱们提供了一个方法来改变这个变换矩阵,那就是transform()。

默认坐标系是以画布最左上角为坐标原点(0,0)。越往右X轴数值越大,越往下Y轴的数值越大。在默认坐标系中,每一个点的坐标都是直接映射到一个CSS像素上。画布上一些特定的操作和属性的设置都使用默认坐标系。然而除了默认坐标系之外,每个画布还有一个还有一个“当前变换距阵”,作为图形状态的一部分。该矩阵定义了画布的当前坐标系。当指定了一个点的坐标后,画布的大部分操作都将该点映射到当前的坐标系中,而不是默认的坐标系。当前变换矩阵是用来指定的坐标转换成为默认坐标系中的等价坐标。坐标的变换还影响了文本和线段的绘制。
 
调用translate()方法只是简单地将坐标原点进行上、下、左、右移动。
rotate()方法会将坐标轴根据指定角度里进行顺时针旋转。
scale()方法实现对x轴或由y轴上的距离进行延长和缩短。传递负值会实现
 
scale以坐标原点做参照点将坐标轴进行翻转。就好像镜子中的镜像。
translate用来将坐标原点移动到画布最左下角,然后scale方法用于实现将y轴进行翻转,这样的就变成了越往上y轴越大。

从数学角度来理解坐标系变换:
translate、rotate和scale方法想象成对坐标轴的变换,就很容易理解了。从代数角度很容易理解坐标变换,就是把变换想像成一个变换后坐标系中的点(x,y),到原来的坐标系统变成了(x`,y`)。
调用 c.translate(dx,dy)。的方法等效如下表达式

复制代码
代码如下:

x` = x+dx; //新系统中的x轴的0,在原系统中就是dx
y` = y+dy;
c.scale(sx,sy);
x` = sx*x;
y` = sy*y;
c.rotate()
x` =x*cos(a)-y*sin(a);
y` = y*cos(a)+x*sin(a);

建议使用transform()的时候,可以在如下几个情况下使用:

1.使用context.transform (1,0,0,1,dx,dy)代替context.translate(dx,dy)
2.使用context.transform(sx,0,0,sy,0,0)代替context.scale(sx, sy)
3.使用context.transform(0,b,c,0,0,0)来实现倾斜效果(最实用)。
不用再使用它去实现旋转了,另外也没有也不用全记这些结论,直接记下abcdef六个参数的意义,效果是一样的。

下面我们看一个代码,熟悉一下:

JavaScript Code复制内容到剪贴板
  1. <!DOCTYPE html>   
  2. <html lang="zh">   
  3. <head>   
  4.     <meta charset="UTF-8">   
  5.     <title>矩阵变换</title>   
  6.     <style>   
  7.         body { background: url("./images/bg3.jpg") repeat; }  
  8.         #canvas { border: 1px solid #aaaaaa; display: block; margin: 50px auto; }   
  9.     </style>   
  10. </head>   
  11. <body>   
  12. <div id="canvas-warp">   
  13.     <canvas id="canvas">   
  14.         你的浏览器居然不支持Canvas?!赶快换一个吧!!   
  15.     </canvas>   
  16. </div>   
  17.   
  18. <script>   
  19.     window.onload = function(){   
  20.         var canvas = document.getElementById("canvas");   
  21.         canvas.width = 800;   
  22.         canvas.height = 600;   
  23.         var context = canvas.getContext("2d");   
  24.         context.fillStyle = "#FFF";   
  25.         context.fillRect(0,0,800,600);   
  26.   
  27.         context.fillStyle = "yellow";   
  28.         context.strokeStyle = "#00AAAA";   
  29.         context.lineWidth = 5;   
  30.   
  31.         context.save();   
  32.         //平移至(300,200)   
  33.         context.transform(1,0,0,1,300,200);   
  34.         //水平方向放大2倍,垂直方向放大1.5倍   
  35.         context.transform(2,0,0,1.5,0,0);   
  36.         //水平方向向右倾斜宽度10%的距离,垂直方向向上倾斜高度10%的距离   
  37.         context.transform(1,-0.1,0.1,1,0,0);   
  38.         context.fillRect(0,0,200,200);   
  39.         context.strokeRect(0,0,200,200);   
  40.         context.restore();   
  41.     };   
  42. </script>   
  43. </body>   
  44. </html>  

运行结果:
深入解析HTML5 Canvas控制图形矩阵变换的方法

setTransform()方法
transform()方法的行为相对于由 rotate(),scale(), translate(), or transform() 完成的其他变换。例如:如果我们已经将绘图设置为放到两倍,则 transform() 方法会把绘图放大两倍,那么我们的绘图最终将放大四倍。这一点和之前的变换是一样的。

但是setTransform()不会相对于其他变换来发生行为。它的参数也是六个,context.setTransform(a,b,c,d,e,f),与transform()一样。

这里我们通过一个例子来说明:
绘制一个矩形,通过 setTransform() 重置并创建新的变换矩阵,再次绘制矩形,重置并创建新的变换矩阵,然后再次绘制矩形。

JavaScript Code复制内容到剪贴板
  1. <!DOCTYPE html>   
  2. <html lang="zh">   
  3. <head>   
  4.     <meta charset="UTF-8">   
  5.     <title>矩阵变换</title>   
  6.     <style>   
  7.         body { background: url("./images/bg3.jpg") repeat; }  
  8.         #canvas { border: 1px solid #aaaaaa; display: block; margin: 50px auto; }   
  9.     </style>   
  10. </head>   
  11. <body>   
  12. <div id="canvas-warp">   
  13.     <canvas id="canvas">   
  14.         你的浏览器居然不支持Canvas?!赶快换一个吧!!   
  15.     </canvas>   
  16. </div>   
  17.   
  18. <script>   
  19.     window.onload = function(){   
  20.         var canvas = document.getElementById("canvas");   
  21.         canvas.width = 800;   
  22.         canvas.height = 600;   
  23.         var context = canvas.getContext("2d");   
  24.         context.fillStyle = "#FFF";   
  25.         context.fillRect(0,0,800,600);   
  26.   
  27.         context.fillStyle="yellow";   
  28.         context.fillRect(200,100,250,100)   
  29.   
  30.         context.setTransform(1,0.5,-0.5,1,30,10);   
  31.         context.fillStyle="red";   
  32.         context.fillRect(200,100,250,100);   
  33.   
  34.         context.setTransform(1,0.5,-0.5,1,30,10);   
  35.         context.fillStyle="blue";   
  36.         context.fillRect(200,100,250,100);   
  37.     };   
  38. </script>   
  39. </body>   
  40. </html>    

运行结果:
深入解析HTML5 Canvas控制图形矩阵变换的方法

解释一下过程:每当我们调用 setTransform() 时,它都会重置前一个变换矩阵然后构建新的矩阵,因此在下面的例子中,不会显示红色矩形,因为它在蓝色矩形下面。

HTML / CSS 相关文章推荐
css3 条纹化和透明化表格Firefox下测试成功
Apr 15 HTML / CSS
详解CSS3原生支持div铺满浏览器的方法
Aug 30 HTML / CSS
CSS3移动端vw+rem不依赖JS实现响应式布局的方法
Jan 23 HTML / CSS
HTML5之SVG 2D入门6—视窗坐标系与用户坐标系及变换概述
Jan 30 HTML / CSS
html5 Web SQL Database 之事务处理函数transaction与executeSQL解析
Nov 07 HTML / CSS
用html5实现语音搜索框的方法
Mar 18 HTML / CSS
利用HTML5中的Canvas绘制一张笑脸的教程
May 07 HTML / CSS
基于HTML5新特性Mutation Observer实现编辑器的撤销和回退操作
Jan 11 HTML / CSS
解决HTML5中的audio在手机端和微信端的不能自动播放问题
Nov 04 HTML / CSS
HTML5 通过Vedio标签实现视频循环播放的示例代码
Aug 05 HTML / CSS
CSS 一行代码实现头像与国旗的融合
Oct 24 HTML / CSS
CSS使用SVG实现动态分布的圆环发散路径动画
Dec 24 HTML / CSS
详解如何用HTML5 Canvas API控制图片的缩放变换
Mar 22 #HTML / CSS
实例讲解利用HTML5 Canvas API操作图形旋转的方法
Mar 22 #HTML / CSS
详解通过HTML5 Canvas实现图片的平移及旋转变化的方法
Mar 22 #HTML / CSS
使用HTML5 Canvas绘制圆角矩形及相关的一些应用举例
Mar 22 #HTML / CSS
使用HTML5 Canvas API绘制弧线的教程
Mar 22 #HTML / CSS
HTML5单页面手势滑屏切换原理
Mar 21 #HTML / CSS
详解HTML5 Canvas绘制不规则图形时的非零环绕原则
Mar 21 #HTML / CSS
You might like
php 模拟 asp.net webFrom 按钮提交事件实例
2014/10/13 PHP
php自定文件保存session的方法
2014/12/10 PHP
Java和PHP在Web开发方面对比分析
2015/03/01 PHP
yii2缓存Caching基本用法示例
2016/07/18 PHP
thinkphp5框架实现数据库读取的数据转换成json格式示例
2019/10/10 PHP
laravel框架模型、视图与控制器简单操作示例
2019/10/10 PHP
gridview生成时如何去掉style属性中的border-collapse
2014/09/30 Javascript
JavaScript DOM事件(笔记)
2015/04/08 Javascript
js实现统计字符串中特定字符出现个数的方法
2016/08/02 Javascript
JS中script标签defer和async属性的区别详解
2016/08/12 Javascript
基于JS实现的随机数字抽签实例
2016/12/08 Javascript
详解js树形控件—zTree使用总结
2016/12/28 Javascript
Vue 框架之动态绑定 css 样式实例分析
2018/11/14 Javascript
vue 更改连接后台的api示例
2019/11/11 Javascript
[01:14:10]2014 DOTA2国际邀请赛中国区预选赛 SPD-GAMING VS Orenda
2014/05/22 DOTA
[01:20]2018DOTA2亚洲邀请赛总决赛战队Mineski晋级之路
2018/04/07 DOTA
Python常用列表数据结构小结
2014/08/06 Python
在Django中创建URLconf相关的通用视图的方法
2015/07/20 Python
利用Python自动监控网站并发送邮件告警的方法
2016/08/24 Python
Python yield 使用方法浅析
2017/05/20 Python
python实现杨辉三角思路
2017/07/14 Python
Python数据结构与算法之图的广度优先与深度优先搜索算法示例
2017/12/14 Python
jupyter 导入csv文件方式
2020/04/21 Python
在tensorflow以及keras安装目录查询操作(windows下)
2020/06/19 Python
世界上获奖最多的手机镜头:Olloclip
2018/03/03 全球购物
英文简历自荐信范文
2013/12/11 职场文书
男方父母婚礼答谢词
2014/01/25 职场文书
珍惜时间演讲稿
2014/05/14 职场文书
我爱家乡演讲稿
2014/09/12 职场文书
作风整顿个人剖析材料
2014/10/06 职场文书
实训报告范文大全
2014/11/04 职场文书
党的群众路线教育实践活动个人对照检查材料(乡镇)
2014/11/05 职场文书
基层工作经历证明
2015/06/19 职场文书
财务年终工作总结大全
2019/06/20 职场文书
2019请假条的基本格式及范文!
2019/07/05 职场文书
python高温预警数据获取实例
2022/07/23 Python