这里对CGAffineTransform和CATransform3D的使用做个记录,比较简单的实现2D和3D的旋转,位移,缩放,锚点相关的有一些问题后续更新
CGAffineTransform是作用于View的主要为2D变换,而CATransform3D主要作用于Layer,为3D变换使用,这两种变换可以转换
CGAffineTransform
cgAffineTransform本身是一个仿射变换矩阵
1.矩阵的基本知识:
struct CGAffineTransform
{
CGFloat a, b, c, d;
CGFloat tx, ty;
};
CGAffineTransform CGAffineTransformMake
(CGFloat a,CGFloat b,CGFloat c,CGFloat d,CGFloat tx,CGFloat ty);
为了把二维图形的变化统一在一个坐标系里,引入了齐次坐标的概念,即把一个图形用一个三维矩阵表示,其中第三列总是(0,0,1),用来作为坐标系的标准。所以所有的变化都由前两列完成。
以上参数在矩阵中的表示为:
|a b 0|
|c d 0|
|tx ty 1|
运算原理:原坐标设为(X,Y,1);
|a b 0|
[X,Y, 1] |c d 0| = [aX + cY +
tx bX + dY + ty 1] ;
|tx ty 1|
通过矩阵运算后的坐标[aX + cY + tx bX + dY + ty 1],我们对比一下可知:
第一种:设a=d=1, b=c=0.
[aX + cY + tx bX + dY + ty 1] = [X + tx Y + ty 1];
可见,这个时候,坐标是按照向量(tx,ty)进行平移,其实这也就是函数
CGAffineTransform CGAffineMakeTranslation(CGFloat tx,CGFloat ty)的计算原理。
第二种:设b=c=tx=ty=0.
[aX + cY + tx bX + dY + ty 1] = [aX dY 1];
可见,这个时候,坐标X按照a进行缩放,Y按照d进行缩放,a,d就是X,Y的比例系数,其实这也就是函数
CGAffineTransform CGAffineTransformMakeScale(CGFloat sx, CGFloat sy)的计算原理。a对应于sx,d对应于sy。
第三种:设tx=ty=0,a=cosɵ,b=sinɵ,c=-sinɵ,d=cosɵ。
[aX + cY + tx bX + dY + ty 1] = [Xcosɵ - Ysinɵ Xsinɵ + Ycosɵ 1] ;
可见,这个时候,ɵ就是旋转的角度,逆时针为正,顺时针为负。其实这也就是函数
CGAffineTransform CGAffineTransformMakeRotation(CGFloat angle)的计算原理。angle即ɵ的弧度表示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
#define DEGREES_TO_RADIANS(angle) ((angle) / 180.0 * M_PI)
//旋转
sender
{
// transformItem.transform = CGAffineTransformIdentity;
// transformItem.layer.anchorPoint = CGPointMake(1,0);
// transformItem.center = CGPointMake(CGRectGetWidth(transformItem.bounds), 0.0);
// transformItem.center = CGPointMake(transformItem.center.x-transformItem.frame.size.width*0.5, transformItem.center.y-transformItem.frame.size.height*0.5);
{
// transformItem.transform = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(-90));
;
{
;
}
//缩放
sender
{
;
;
;
{
// transformItem.transform = CGAffineTransformScale(transformItem.transform, 0.5, 0.5);
;
// transformItem.center = CGPointMake(0,h);
{
;
}
//位移
sender
{
{
;
{
;
}
|
CATransform3D
CATransform3D也是个矩阵,多了一些切变和Z轴的值,这里通过CABasicAnimation来实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
|
sender
{
;
;
}
sender
{
;
;
}
sender
{
;
;
;
}
//- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
//{
// //这边为什么是nil? :(
//#if 1
// //识别动画
// //?debug发现两者的地址不一样,这个问题很纠结
// if ([anim isEqual:m_pGroupAnimation])//[m_pMyImageView.layer valueForKey:ANIM_GROUP])
// {
// [m_pMyImageView removeFromSuperview];
// [m_pMyImageView release];
//
// }
//#else
// //这种方法,虽然能解决方法,但是处理多个CAAnimationGroup动画或者CAAnimation动画时,就不能有效处理,方法待定
// //这组动画结束,移除视图
// if ([anim isKindOfClass:[CAAnimationGroup class]])
// {
// //这边为什么是nil? :(
//
// [m_pMyImageView removeFromSuperview];
// [m_pMyImageView release];
//
// }
//#endif
//}
animationShrink
{
;
;
;
;
;
//设置动画代理
;
;
}
animationFallingDown
{
//falling down animation:
;
;
;
;
;
;
//设置动画代理
;
;
}
animationRotate
{
// rotate animation
;
;
;
;
;
;
;
//设置开始时间,能够连续播放多组动画
;
//设置动画代理
;
;
}
|