CoreAnimation 變換
????CoreAnimation 目錄
????博客園MakeDown支持不佳,如有需要請進GitHub
????本片博客主要內容:
- 仿射變換 - CGAffineTransform
- 3D變換 - CATransform3D
仿射變換 - CGAffineTransform
???? CGAffineTransform
是用于二維空間的旋轉,縮放和平移的屬性.首先展示一個簡單的樣例,將圖片順時針旋轉45°??.

CGAffineTransform transform = CGAffineTransformIdentity;
transform = CGAffineTransformRotate(transform, M_PI_4);
self.imageView.layer.affineTransform = transform;
????向右平移200??.

CGAffineTransform transform = CGAffineTransformIdentity;
transform = CGAffineTransformTranslate(transform, 200, 0);
self.imageView.layer.affineTransform = transform;
????先進行旋轉后進行向右平移??.

CGAffineTransform transform = CGAffineTransformIdentity;
transform = CGAffineTransformRotate(transform, M_PI_4);
transform = CGAffineTransformTranslate(transform, 200, 0);
self.imageView.layer.affineTransform = transform;
注意:
圖片二與圖片三同是向右平移200,但是通過觀察兩圖的對比不難發現,圖片三的平移距離明顯比圖片二的距離小,與此同時圖片三相對圖片二向下也有一定的平移,這是因為transform
的上一次設置會對下一次設置的效果產生影響.
????混合變換方法 CGAffineTransformConcat
??.

CGAffineTransform transform = CGAffineTransformIdentity;
transform = CGAffineTransformRotate(transform, M_PI_4);
CGAffineTransform transformTwo = CGAffineTransformMakeTranslation(-200, 0);
transform = CGAffineTransformConcat(transform, transformTwo);
self.imageView.layer.affineTransform = transform;
3D變換 - CATransform3D
???? CATransform3D
支持圖層在三維空間內的操作,x軸旋轉??.

CATransform3D transform3d = CATransform3DIdentity;
transform3d = CATransform3DRotate(transform3d, M_PI_4, 1, 0, 0);
self.imageView.layer.transform = transform3d;
????y軸旋轉??.

CATransform3D transform3d = CATransform3DIdentity;
transform3d = CATransform3DRotate(transform3d, M_PI_4, 0, 1, 0);
self.imageView.layer.transform = transform3d;
????z軸旋轉??.

CATransform3D transform3d = CATransform3DIdentity;
transform3d = CATransform3DRotate(transform3d, M_PI_4, 0, 0, 1);
self.imageView.layer.transform = transform3d;
????以上三張樣圖只能讓我們發現與原有圖片有所不同,但是不能明顯的區別出差別在哪里,此時我們可以設置m34
來實現透視投影的效果.
????透視投影 - x軸旋轉??.

CATransform3D transform3d = CATransform3DIdentity;
transform3d.m34 = - 1.0 / 500.0;
transform3d = CATransform3DRotate(transform3d, M_PI_4, 1, 0, 0);
self.imageView.layer.transform = transform3d;
????透視投影 - y軸旋轉??.

CATransform3D transform3d = CATransform3DIdentity;
transform3d.m34 = - 1.0 / 500.0;
transform3d = CATransform3DRotate(transform3d, M_PI_4, 0, 1, 0);
self.imageView.layer.transform = transform3d;
????透視投影 - z軸旋轉??.

CATransform3D transform3d = CATransform3DIdentity;
transform3d.m34 = - 1.0 / 500.0;
transform3d = CATransform3DRotate(transform3d, M_PI_4, 0, 0, 1);
self.imageView.layer.transform = transform3d;
????滅點
: 當在透視角度繪圖的時候,遠離相機視角的物體將會變小變遠,當遠離到一個極限距離,它們就縮成了一個點,因此所有的物體最后都匯聚消失在同一個點.在現實中,這個點通常是視圖的中心,于是為了在應用中創建擬真效果的透視,這個點應該聚在屏幕中點,或者至少是包含所有3D對象的視圖中點.

????了解滅點
后便會遇到一個問題,通常狀態下手機屏幕所顯示的內容存在著很多圖層,那么我們要一一設置他們的滅點嗎?顯然這種方法是不可行的以為它十分不方便.封裝?或許是一個錯的方法,但是那樣會帶來一個嚴重的后果就是不靈活,那么應該怎樣去做?sublayerTransform
是最完美的選擇,它也是CATransform3D類型,但和對一個圖層的變換不同,它影響到所有的子圖層.這意味著你可以一次性對包含這些圖層的容器做變換,于是所有的子圖層都自動繼承了這個變換方法.
????做一個簡單的測試.

CATransform3D perspective = CATransform3DIdentity;
perspective.m34 = - 1.0 / 500;
self.view.layer.sublayerTransform = perspective;
CATransform3D transform = CATransform3DIdentity;
CATransform3D twoTransform = CATransform3DIdentity;
transform = CATransform3DRotate(transform, M_PI_4, 0, 1, 0);
twoTransform = CATransform3DRotate(twoTransform, -M_PI_4, 0, 1, 0);
self.imageView.layer.transform = transform;
self.imageTwoView.layer.transform = twoTransform;
???? 背面
: 設置圖層翻轉180°.

CATransform3D perspective = CATransform3DIdentity;
perspective.m34 = - 1.0 / 500;
self.view.layer.sublayerTransform = perspective;
CATransform3D transform = CATransform3DIdentity;
CATransform3D twoTransform = CATransform3DIdentity;
transform = CATransform3DRotate(transform, M_PI_4, 0, 1, 0);
twoTransform = CATransform3DRotate(twoTransform, -M_PI, 0, 1, 0);
self.imageView.layer.transform = transform;
self.imageTwoView.layer.transform = twoTransform;
????背面的繪制是很浪費cpu以及gpu的,因此我們更多的時候是需要禁止繪制圖層背面的.

CATransform3D perspective = CATransform3DIdentity;
perspective.m34 = - 1.0 / 500;
self.view.layer.sublayerTransform = perspective;
CATransform3D transform = CATransform3DIdentity;
CATransform3D twoTransform = CATransform3DIdentity;
transform = CATransform3DRotate(transform, M_PI_4, 0, 1, 0);
twoTransform = CATransform3DRotate(twoTransform, -M_PI, 0, 1, 0);
self.imageView.layer.transform = transform;
self.imageTwoView.layer.transform = twoTransform;
self.imageTwoView.layer.doubleSided = NO;// 不繪制背面
????最后來討論一下,子圖的相對父圖層的逆變換是否會恢復原狀.z軸?

CATransform3D perspective = CATransform3DIdentity;
perspective.m34 = - 1.0 / 500;
self.view.layer.sublayerTransform = perspective;
CATransform3D outer = CATransform3DIdentity;
CATransform3D inter = CATransform3DIdentity;
outer = CATransform3DRotate(outer, M_PI_4, 0, 0, 1);
inter = CATransform3DRotate(inter, -M_PI_4, 0, 0, 1);
self.outer.layer.transform = outer;
self.inter.layer.transform = inter;
????z軸狀態下是可以恢復原狀的.y軸?

CATransform3D perspective = CATransform3DIdentity;
perspective.m34 = - 1.0 / 500;
self.view.layer.sublayerTransform = perspective;
CATransform3D outer = CATransform3DIdentity;
CATransform3D inter = CATransform3DIdentity;
outer = CATransform3DRotate(outer, M_PI_4, 0, 1, 0);
inter = CATransform3DRotate(inter, -M_PI_4, 0, 1, 0);
self.outer.layer.transform = outer;
self.inter.layer.transform = inter;
y軸并不是,這是由于盡管Core Animation圖層存在于3D空間之內,但它們并不都存在同一個3D空間.每個圖層的3D場景其實是扁平化的,當你從正面觀察一個圖層,看到的實際上由子圖層創建的想象出來的3D場景,但當你傾斜這個圖層,你會發現實際上這個3D場景僅僅是被繪制在圖層的表面.