55- [ 齐次坐标系入门级思考] ( https://oncemore2020.github.io/blog/homogeneous/ )
66- [ 仿射变换与齐次坐标] ( https://guangchun.wordpress.com/2011/10/12/affineandhomogeneous/ )
77
8+ 读完本文,相信你能够搞明白以下三个问题:
9+
10+ - 为什么 Matrix 是个 3 X 3 的矩阵
11+ - Matrix 这个 3 X 3 的矩阵每个元素的作用
12+ - Matrix 的 setXXX、preXXX、postXXX API 方法的工作原理
13+
814## Matrix 的结构
915
1016Matrix 是 Android SDK 提供的一个矩阵类,它代表一个 3 X 3 的矩阵(不懂矩阵为何物的童鞋就要自行 Google 了)。 Matrix 提供了让我们获得 Matrix 值的 API —— ** getValues**
@@ -23,83 +29,103 @@ Matrix 是 Android SDK 提供的一个矩阵类,它代表一个 3 X 3 的矩
2329
2430![ ] ( http://d.hiphotos.baidu.com/image/pic/item/2934349b033b5bb5425dd68d3ed3d539b600bc3f.jpg )
2531
26- 没错,我们平常利用 Matrix 来进行 Translate(平移)、Scale(缩放)、Rotate(旋转)的操作,实际上就是在操作着这个矩阵中元素的数值来达到我们想要的效果 。但是现在问题来了,上面提到的平移、缩放、旋转操作中,旋转和缩放可以用乘法表示,而平移就只能用加法表示,而且 Matrix 是一个 3 X 3 的矩阵,实际上表示这些操作 2 X 2 的矩阵足矣!
32+ 实际上我们平常利用 Matrix 来进行 Translate(平移)、Scale(缩放)、Rotate(旋转)的操作,就是在操作着这个矩阵中元素的数值来达到我们想要的效果 。但是现在问题来了,上面提到的平移、缩放、旋转操作中,旋转和缩放可以用乘法表示,而平移就只能用加法表示,而且 Matrix 是一个 3 X 3 的矩阵,实际上表示这些操作 2 X 2 的矩阵足矣!
2733
2834![ ] ( http://e.hiphotos.baidu.com/image/pic/item/7acb0a46f21fbe096feccf6063600c338744ad17.jpg )
2935
3036![ ] ( http://h.hiphotos.baidu.com/image/pic/item/bf096b63f6246b600bbcbe00e3f81a4c510fa217.jpg )
3137
3238![ ] ( http://c.hiphotos.baidu.com/image/pic/item/d058ccbf6c81800a737a857ab93533fa828b4722.jpg )
3339
34- 如上,可以依次看到平移、缩放、旋转的矩阵,其中(x',y')表示执行操作后的点的坐标,(x,y)表示执行操作前的点的坐标。tx、ty 分别表示x轴、y轴上平移的距离,Sx、Sy 分别表示x轴、y轴上的缩放比例,θ 则表示旋转角度。至于上面矩阵的推导过程,Google一下其实很多,这里就不去赘述了。以前到了这里,我就会很纳闷,为什么 2 X 2 矩阵能干的事情,偏偏要用 3 X 3 矩阵去做,直到遇到前面提到的两篇文章才有所领悟。
40+ 如上,可以依次看到平移、缩放、旋转的矩阵,其中
3541
36- 其实在计算机图形应用涉及到几何变换,主要包括平移、旋转、缩放。以矩阵表达式来计算这些变换时,平移是矩阵相加,旋转和缩放则是矩阵相乘。那些数学大神们为了方便计算,所以引入了一样神器叫做** 齐次坐标** (不懂得童鞋,老规矩自行搜索),将平移的加法合并用乘法表示。所以,2 X 2 的矩阵经过一番变换后,成了下面这样的。
42+ - (x',y')表示执行操作后的点的坐标,(x,y)表示执行操作前的点的坐标
43+ - tx、ty 分别表示x轴、y轴上平移的距离,Sx、Sy 分别表示x轴、y轴上的缩放比例
44+ - θ 则表示旋转角度
45+
46+ 至于上面矩阵的推导过程,网络上很多,这里就不去赘述了。以前到了这里,我就会很纳闷,为什么 2 X 2 矩阵能干的事情,偏偏要用 3 X 3 矩阵去做,直到遇到前面提到的两篇文章才有所领悟。
47+
48+ 其实在计算机图形应用涉及到几何变换,主要包括平移、旋转、缩放。以矩阵表达式来计算这些变换时,平移是矩阵相加,旋转和缩放则是矩阵相乘。那些数学大神们为了方便计算,所以引入了一样神器叫做** 齐次坐标** (不懂的童鞋,老规矩自行搜索),将平移的加法合并用乘法表示。所以,2 X 2 的矩阵经过一番变换后,成了下面这样的。
3749
3850![ ] ( http://h.hiphotos.baidu.com/image/pic/item/5d6034a85edf8db184610e100123dd54564e7472.jpg )
3951
4052![ ] ( http://b.hiphotos.baidu.com/image/pic/item/c83d70cf3bc79f3d89569944b2a1cd11728b290a.jpg )
4153
4254![ ] ( http://b.hiphotos.baidu.com/image/pic/item/5fdf8db1cb13495458519a105e4e9258d1094a72.jpg )
4355
44- ## 验证结果
45-
46- ## 总结
47-
56+ 至此,我们可以得知** 为什么 Matrix 是一个 3 X 3 的矩阵** ,其实 2 X 2 的矩阵是足以表示的,不过是为了方便计算而合并写成了 3 X 3 的格式。
4857
58+ ## Matrix 元素的作用
4959
50- ## applyTransformation
60+ 一个 Matrix 共有 9 个元素,那么它每个元素的值发生改变会起到什么作用呢?按照前面所示的齐次坐标转换得到 3 X 3 的矩阵和 Android 文档提供的官方结构相对应,我们不难看出下面的对应关系(其实从 Matrix 中每个位置的常量命名也可以看出来):
5161
52- 传入两个参数 void applyTransformation (float interpolatedTime, Transformation t )
62+ ![ ] ( http://f.hiphotos.baidu.com/image/pic/item/aec379310a55b3193603a1034ba98226cefc17c9.jpg )
5363
54- interpolatedTime:时间比例系数,由0变化到1;
55- t:包含两个部分,一个Alpha值和一个Matrix矩阵,Matrix默认是一个3X3的单位矩阵
64+ ![ ] ( http://e.hiphotos.baidu.com/image/pic/item/562c11dfa9ec8a136f837496ff03918fa0ecc02e.jpg )
5665
57- https ://developer.android. com/reference/android/view/animation/Animation.html#applyTransformation (float, android.view.animation.Transformation )
66+ ![ ] ( http ://b.hiphotos.baidu. com/image/pic/item/aa64034f78f0f73676046f770255b319eac413c9.jpg )
5867
59- ## Animation API小结
68+ 从这我们可以看出这个 Matrix 结构中的每个参数发挥着如下作用:
6069
61- 可以在xml中做的,也可以在代码里面做到
70+ - MTRANS_X、MTRANS_Y 同时控制着 Translate
71+ - MSCALE_X、MSCALE_Y 同时控制着 Scale
72+ - MSCALE_X、MSKEW_X、MSCALE_Y、MSKEW_Y 同时控制着 Rotate
73+ - 从名称上看,我们可以顺带看出 MSKEW_X、MSKEW_Y 同时控制着 Skew
6274
63- 动画的构造函数参数要么是绝对的像素值,要么是相对某个View的比例值 。
75+ 如果要进行代码验证的话,也非常简单,例如直接只对 Matrix 做 Translate 的 API 调用操作,再将 Matrix 的信息打印到控制台,你会发现整个 Matrix 确实只有 MTRANS_X、MTRANS_Y 两个位置的数字在发生变化。其他 Scale、Rotate、Skew 操作也是一样,感兴趣的童鞋可以自行代码验证一番 。
6476
65- ## Animation 实现原理
77+ 至此,我们可以大致弄清矩阵每个元素的作用。至于 MPERSP_0、MPERSP_1、MPERSP_2 这三个参数,目前暂时不得而知,网上有文章说这三个参数控制着透视变换,但是文档和 API 上都没怎么提及,所以还是有待验证研究的,有明白的童鞋不妨留言赐教一下,不胜感激。
6678
67- 研究动画,如何实现,应该对其原理进行分析才对。
79+ ## 理解 Matrix API 调用
6880
69- 跟 View 的绘制原理有关,需要了解。
81+ 按照第一小节里面通过齐次坐标转换而来的矩阵方程可以知道,假设一根线执行了平移操作,相当于线上每个点的坐标被下方的矩阵左乘。(缩放和旋转操作也是同理)
7082
71- Android 动画框架详解: https ://www.ibm. com/developerworks/cn/opensource/os-cn-android-anmt1/
83+ ![ ] ( http ://f.hiphotos.baidu. com/image/pic/item/5882b2b7d0a20cf49c1f77a87e094b36acaf993e.jpg )
7284
73- ## 自定义 Animation
85+ 如果要进行同时缩放、平移之类的符合变化操作,也无非就是选取相应的矩阵做左乘操作。为了加深矩阵变换对应 Matrix API 调用的理解,直接通过下面的一个自定义的动画效果和代码来讲解好了。
7486
75- http://www.cnblogs.com/wondertwo/p/5295976.html
87+ ``` java
7688
77- 矩阵知识,以及矩阵生成的XY轴的图如何展示(有什么工具可以画出来吗)
89+ public class SimpleCustomAnimation extends Animation {
7890
79- 例子: http://www.apkbus.com/blog-104974-52806.html
91+ private int mWidth, mHeight;
8092
93+ @Override
94+ public void initialize (int width , int height , int parentWidth , int parentHeight ) {
95+ super . initialize(width, height, parentWidth, parentHeight);
96+ this . mWidth = width;
97+ this . mHeight = height;
98+ }
8199
82- ## 关于 Matrix
100+ @Override
101+ protected void applyTransformation (float interpolatedTime , Transformation t ) {
102+ Matrix matrix = t. getMatrix();
103+ Matrix matrix = t. getMatrix();
104+ matrix. preScale(interpolatedTime, interpolatedTime);// 缩放
105+ matrix. preRotate(interpolatedTime * 360 );// 旋转
106+ // 下面的Translate组合是为了将缩放和旋转的基点移动到整个View的中心,不然系统默认是以View的左上角作为基点
107+ matrix. preTranslate(- mWidth / 2 , - mHeight / 2 );
108+ matrix. postTranslate(mWidth / 2 , mHeight / 2 );
109+ }
110+ }
83111
84- Matrix 是一个 3 X 3 的矩阵
112+ ```
85113
86- 不懂矩阵的乘法,可以查看阮一峰先生的博文 [ 理解矩阵乘法 ] ( http://www.ruanyifeng.com/blog/2015/09/matrix-multiplication.html ) ,或者去维基百科。
114+ 熟悉动画这块的童鞋肯定知道,Animation 就是通过不断改变 applyTransformation 函数传入的 Matrix 来实现各种各样的动画效果的,通过上面 applyTransformation 寥寥的几行 Matrix 的复合变换操作可以得到如下效果
87115
88- 详细介绍 Android Matrix 矩阵的文章:
116+ ![ ] ( http://f.hiphotos.baidu.com/image/pic/item/9358d109b3de9c82048c06f86481800a18d843d8.jpg )
89117
90- Android Matrix矩阵详解: http://www.maplejaw.com/2016/06/21/Android-Matrix%E7%9F%A9%E9%98%B5%E8%AF%A6%E8%A7%A3/index.html
118+ 实际上这几行代码用矩阵来表示就相当于如下所示:
91119
92- Android Matrix: http://www.cnblogs. com/qiengo/archive/2012/06/30/2570874.html (透视那块,既然文档没有提,那就稍作解释然后忽略即可)
120+ ![ ] ( http://d.hiphotos.baidu. com/image/pic/item/c8ea15ce36d3d539cd1eedb43287e950352ab0a2.jpg )
93121
94- 矩阵的左乘右乘法概念:
122+ 关于代码的作用上边已经给出了注释,这里就不多写了。主要还是要弄明白 Matrix 复合变换中 pre 、 post 等操作与其对应的矩阵发生的左乘、右乘变化。
95123
96- http://www.cnblogs.com/ylwn817/archive/2011/12/15/2288921.html
97-
98- http://blog.csdn.net/linmiansheng/article/details/18820599
124+ ## 总结
99125
100- 2D平面中关于矩阵( Matrix)跟图形变换的讲解: http://blog.csdn.net/linmiansheng/article/details/18801947
126+ 到此,整篇文章已经完结,相信已经能够让你明白开头提到的三个问题。其实我们也可以发现,Google 封装了 Matrix 已经是很完美了,几乎屏蔽了所有的数学细节,使得我这种数学水平一般的开发者也能够去调用相应的 API 实现一些简单的效果。虽然被封装得很完美,但掌握相应的一些原理,依旧可以帮你更好的理解一些技术实现,此次加深了对 Matrix 一些操作的理解,帮我自己解决了以前不少的困惑,不知道有没有帮你 get 到一些什么呢?
101127
102- 对于其次坐标的理解: https://oncemore2020. github.io/blog/homogeneous/
128+ 上面给的示例代码很简单,复制黏贴即可运行玩耍,实在需要直接运行源码的童鞋就到 https://github.com/D-clock/AndroidStudyCode 找吧!
103129
104130
105131
0 commit comments