16/04/25 第五章 变换
仿射变换 CGAffineTransform
CGAffineTransform
是一个3*2的矩阵,可以和二维空间向量做乘法. 主要用于平移,旋转,缩放.- 当对图层应用变换矩阵,图层矩形内的每一个点都被相应地做变换,从而形成一个新的四边形的形状。
CGAffineTransform
中的“仿射”的意思是无论变换矩阵用什么值,图层中平行的两条线在变换之后任然保持平行,CGAffineTransform
可以做出任意符合上述标注的变换. Core Graphics
提供了一系列函数来帮助完全没有数学基础的开发者.UIView
可通过transform
进行变换, 事实上UIView
的transform
封装了CALayer
的affineTransform
.CALayer
也有一个transform
属性,类型是CATransform3D
.弧度与角度换算宏
#define RADIANS_TO_DEGREES(x) ((x)/M_PI*180.0)
#define DEGREES_TO_RADIANS(x) ((x)/180.0*M_PI)
-
混合变换
Core Graphics
提供了一系列的函数可以在一个变换的基础上做更深层次的变换,如果做一个既要缩放又要旋转的变换,这就会非常有用了。例如下面几个函数:
CGAffineTransformRotate(CGAffineTransform t, CGFloat angle)
CGAffineTransformScale(CGAffineTransform t, CGFloat sx, CGFloat sy)
CGAffineTransformTranslate(CGAffineTransform t, CGFloat tx, CGFloat ty)
当操纵一个变换的时候,初始生成一个什么都不做的变换很重要–也就是创建一个CGAffineTransform
类型的空值,矩阵论中称作单位矩阵,Core Graphics
同样也提供了一个方便的常量:
CGAffineTransformIdentity
最后,如果需要混合两个已经存在的变换矩阵,就可以使用如下方法,在两个变换的基础上创建一个新的变换:
CGAffineTransformConcat(CGAffineTransform t1, CGAffineTransform t2);
-
3D变换 - CATransform3D
CG的前缀告诉我们,CGAffineTransform类型属于Core Graphics框架,Core Graphics实际上是一个严格意义上的2D绘图API,并且CGAffineTransform仅仅对2D变换有效。
在第三章中,我们提到了zPosition属性,可以用来让图层靠近或者远离相机(用户视角),transform属性(CATransform3D类型)可以真正做到这点,即让图层在3D空间内移动或者旋转。
和CGAffineTransform类似,CATransform3D也是一个矩阵,但是和2x3的矩阵不同,CATransform3D是一个可以在3维空间内做变换的4x4的矩阵
CATransform3DMakeRotation(CGFloat angle, CGFloat x, CGFloat y, CGFloat z)
CATransform3DMakeScale(CGFloat sx, CGFloat sy, CGFloat sz)
CATransform3DMakeTranslation(Gloat tx, CGFloat ty, CGFloat tz)
以旋转为例, 当只是设置了旋转角度和坐标轴时, 显示结果并不是3D效果, 需要设置矩阵内的
m34
属性进行透视投影.
透视投影
- CATransform3D的透视效果通过一个矩阵中一个很简单的元素来控制:
m34
。 m34
用于按比例缩放X和Y的值来计算到底要离视角多远.m34
默认值为0,可通过设置m34
为-1.0 / d来应用透视效果,d代表了想象中视角相机和屏幕之间的距离,以像素为单位. 距离并不重要,可以通过运行来估算一个. 通常为500-1000.1
2
3
4
5
6
7CATransform3D transform = CATransform3DIdentity;
transform.m34 = - 1.0 / 500.0;
transform = CATransform3DRotate(transform, M_PI_4, 0, 1, 0);
self.layerView.layer.transform = transform;
灭点
当在透视角度绘图的时候,远离相机视角的物体将会变小变远,当远离到一个极限距离,它们可能就缩成了一个点,于是所有的物体最后都汇聚消失在同一个点。
当改变一个图层的position,你也改变了它的灭点,做3D变换的时候要时刻记住这一点,当你视图通过调整m34来让它更加有3D效果,应该首先把它放置于屏幕中央,然后通过平移来把它移动到指定位置(而不是直接改变它的position),这样所有的3D图层都共享一个灭点。这样做非常麻烦, 可以通过
sublayerTransform属性
来统一设置灭点(灭点在容器图层中点),可以随意使用position和frame来放置子图层,而不需要把它们放置在屏幕中点,然后为了保证统一的灭点用变换来做平移
待续...