[iOS Animation]-CALayer 3D变换

3D变换

CG的前缀告诉咱们,CGAffineTransform类型属于Core Graphics框架,Core Graphics其实是一个严格意义上的2D绘图API,而且CGAffineTransform仅仅对2D变换有效。 git

在第三章中,咱们提到了zPosition属性,能够用来让图层靠近或者远离相机(用户视角),transform属性(CATransform3D类型)能够真正作到这点,即让图层在3D空间内移动或者旋转。 github

和CGAffineTransform相似,CATransform3D也是一个矩阵,可是和2x3的矩阵不一样,CATransform3D是一个能够在3维空间内作变换的4x4的矩阵(图5.6)。 app

图5.6

图5.6 对一个3D像素点作CATransform3D矩阵变换 框架

和CGAffineTransform矩阵相似,Core Animation提供了一系列的方法用来建立和组合CATransform3D类型的矩阵,和Core Graphics的函数相似,可是3D的平移和旋转多处了一个z参数,而且旋转函数除了angle以外多出了x,y,z三个参数,分别决定了每一个坐标轴方向上的旋转: 函数

CATransform3DMakeRotation(CGFloat angle, CGFloat x, CGFloat y, CGFloat z); CATransform3DMakeScale(CGFloat sx, CGFloat sy, CGFloat sz); CATransform3DMakeTranslation(Gloat tx, CGFloat ty, CGFloat tz);

 

你应该对X轴和Y轴比较熟悉了,分别以右和下为正方向(回忆第三章,这是iOS上的标准结构,在Mac OS,Y轴朝上为正方向),Z轴和这两个轴分别垂直,指向视角外为正方向(图5.7)。 spa

图5.7

图5.7 X,Y,Z轴,以及围绕它们旋转的方向 code

由图所见,绕Z轴的旋转等同于以前二维空间的仿射旋转,可是绕X轴和Y轴的旋转就突破了屏幕的二维空间,而且在用户视角看来发生了倾斜。 orm

举个例子:清单5.4的代码使用了CATransform3DMakeRotation对视图内的图层绕Y轴作了45度角的旋转,咱们能够把视图向右倾斜,这样会看得更清晰。 视频

结果见图5.8,但并不像咱们期待的那样。 get

清单5.4 绕Y轴旋转图层

复制代码
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //rotate the layer 45 degrees along the Y axis CATransform3D transform = CATransform3DMakeRotation(M_PI_4, 0, 1, 0); self.layerView.layer.transform = transform; } @end
复制代码

 

图5.8

图5.8 绕y轴旋转45度的视图

看起来图层并无被旋转,而是仅仅在水平方向上的一个压缩,是哪里出了问题呢?

其实彻底没错,视图看起来更窄其实是由于咱们在用一个斜向的视角看它,而不是透视

透视投影

在真实世界中,当物体远离咱们的时候,因为视角的缘由看起来会变小,理论上说远离咱们的视图的边要比靠近视角的边跟短,但实际上并无发生,而咱们当前的视角是等距离的,也就是在3D变换中任然保持平行,和以前提到的仿射变换相似。

在等距投影中,远处的物体和近处的物体保持一样的缩放比例,这种投影也有它本身的用处(例如建筑绘图,颠倒,和伪3D视频),但当前咱们并不须要。

为了作一些修正,咱们须要引入投影变换(又称做z变换)来对除了旋转以外的变换矩阵作一些修改,Core Animation并无给咱们提供设置透视变换的函数,所以咱们须要手动修改矩阵值,幸运的是,很简单:

CATransform3D的透视效果经过一个矩阵中一个很简单的元素来控制:m34。m34(图5.9)用于按比例缩放X和Y的值来计算到底要离视角多远。

图5.9

图5.9 CATransform3D的m34元素,用来作透视

m34的默认值是0,咱们能够经过设置m34为-1.0 / d来应用透视效果,d表明了想象中视角相机和屏幕之间的距离,以像素为单位,那应该如何计算这个距离呢?实际上并不须要,大概估算一个就行了。

由于视角相机实际上并不存在,因此能够根据屏幕上的显示效果自由决定它的防止的位置。一般500-1000就已经很好了,但对于特定的图层有时候更小后者更大的值会看起来更舒服,减小距离的值会加强透视效果,因此一个很是微小的值会让它看起来更加失真,然而一个很是大的值会让它基本失去透视效果,对视图应用透视的代码见清单5.5,结果见图5.10。

清单5.5 对变换应用透视效果

复制代码
@implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //create a new transform CATransform3D transform = CATransform3DIdentity; //apply perspective transform.m34 = - 1.0 / 500.0; //rotate by 45 degrees along the Y axis transform = CATransform3DRotate(transform, M_PI_4, 0, 1, 0); //apply to layer self.layerView.layer.transform = transform; } @end
复制代码

 

图5.10

图5.10 应用透视效果以后再次对图层作旋转

相关文章
相关标签/搜索