[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 應用透視效果以後再次對圖層作旋轉

相關文章
相關標籤/搜索