坐標(biāo)系
圖層有兩種坐標(biāo)系,分別是基于點(diǎn)坐標(biāo)系和基于單元坐標(biāo)系。這兩種坐標(biāo)系的圓點(diǎn)都在左上角,向右為正x,向下為正y。
點(diǎn)坐標(biāo)系
圖層的位置使用點(diǎn)坐標(biāo)系。通常用bounds和position屬性來指定圖層的大小和位置。bounds屬性定義了圖層的坐標(biāo)系統(tǒng)和包含在屏幕中的尺寸,position屬性定義它相對于父坐標(biāo)系的位置。即便圖層有frame屬性,但它是由bounds和position推導(dǎo)而來的,并太常用。

position屬性是圖層的中央。圖層的anchorPoint屬性改變時(shí),會(huì)影響一些屬性的值,position是其中之一。
單元坐標(biāo)系
圖層的一些屬性使用單元坐標(biāo)系。單元坐標(biāo)x和y的取值范圍是[0,1],x軸最左邊是0最右邊是1,y軸最上邊是0最下邊是1。00為左上角,11位右下角,0.5和0.5就是圖層的中心點(diǎn)。錨點(diǎn)anchorPoint是使用單元坐標(biāo)系的屬性之一,它指定了bounds相對于position的值,也是圖層變換時(shí)的支點(diǎn)。

默認(rèn)anchorPoint的值是0.5,0.5
幾何
position和anchorPoint都是相對于父視圖的位置,坐標(biāo)系不同。但anchorPoint決定落在position點(diǎn)上的位置和旋轉(zhuǎn)等屬性的作用點(diǎn)。bounds表示圖層的圓點(diǎn)和大小。
默認(rèn)情況anchorPoint的值是CGPointMake(0.5, 0.5)
我做了一個(gè)demo,讓一個(gè)粉色的正方形顯示在視圖中央。
CALayer *layer1 = [CALayer layer];
layer1.bounds = CGRectMake(0, 0, 100, 100);
layer1.position = self.view.center;
layer1.anchorPoint = CGPointMake(0.5, 0.5);
layer1.backgroundColor = [UIColor colorWithRed:0.9 green:0.3 blue:0.3 alpha:0.5].CGColor;
[self.view.layer addSublayer:layer1];

然后我再添加一個(gè)藍(lán)色的正方形,把他們的position都設(shè)置成視圖的中央,并修改他們anchorPoint的值。
CALayer *layer1 = [CALayer layer];
layer1.bounds = CGRectMake(0, 0, 100, 100);
layer1.position = self.view.center;
layer1.anchorPoint = CGPointMake(0, 0);
layer1.backgroundColor = [UIColor colorWithRed:0.9 green:0.3 blue:0.3 alpha:0.5].CGColor;
[self.view.layer addSublayer:layer1];
CALayer *layer2 = [CALayer layer];
layer2.bounds = CGRectMake(0, 0, 100, 100);
layer2.position = self.view.center;
layer2.anchorPoint = CGPointMake(1,1);
layer2.backgroundColor = [UIColor colorWithRed:0.3 green:0.3 blue:0.9 alpha:0.5].CGColor;
[self.view.layer addSublayer:layer2];

運(yùn)行發(fā)現(xiàn),anchorPoint的點(diǎn)落在了position上面。
對這兩個(gè)正方形進(jìn)行旋轉(zhuǎn)
CATransform3D transform = CATransform3DIdentity;
transform = CATransform3DRotate(transform, M_PI / 18., 0, 0, 1);
layer1.transform = transform;
layer2.transform = transform;

運(yùn)行發(fā)現(xiàn),兩個(gè)正方形是沿著anchorPoint的點(diǎn)進(jìn)行旋轉(zhuǎn)。
接著打印出frame的值
(origin = (x = 189.63518223330698, y = 368), size = (width = 115.8455930679138, height = 115.84559306791385))
frame是由position,bounds,anchorPoint和transform 屬性共同得到的。
簡單概括一下,anchorPoint就相當(dāng)于一個(gè)幾何特性變換時(shí)的作用中心。它們圍繞這個(gè)點(diǎn)進(jìn)行指定的一系列變換。
以上都是2D情況下的改變,CALayer對象本質(zhì)是3D空間內(nèi)對2D平面的管理。圖層的zPosition屬性值指定了該圖層位于Z軸上面位置,zPosition用于設(shè)置圖層相對于圖層的同級圖層的可視位置。
幾何變換
圖層可以使用一個(gè)CATransform3D矩陣來進(jìn)行圖層的旋轉(zhuǎn),縮放,偏移,歪斜和應(yīng)用的透視等變換。圖層變換的兩個(gè)屬性是transform和sublayerTransform,他們作用在anchorPoint點(diǎn)上,分別針對圖層和自圖層變換。
CATransform3D可以通過三種方式修改
- 使用CATransform3D函數(shù)
- 直接修改數(shù)據(jù)結(jié)構(gòu)
- 使用鍵值編碼修改
CATransform3D函數(shù)
QuartzCore提供一些變換函數(shù),可以直接生成一個(gè)CATransform3D矩陣,對圖層進(jìn)行變換。
- CATransform3DIdentity 單位矩陣,沒有進(jìn)行任何變換。值為[1 0 0 0; 0 1 0 0; 0 0 1 0; 0 0 0 1]
- CATransform3DMakeTranslation 平移,3個(gè)參數(shù)分別針對xyz軸進(jìn)行變換
- CATransform3DTranslate 平移,增加一個(gè)矩陣參數(shù),相當(dāng)于對這個(gè)矩陣做平移效果的疊加
- CATransform3DMakeScale 縮放,3個(gè)參數(shù)分別針對xyz軸進(jìn)行變換
- CATransform3DScale 縮放,增加一個(gè)矩陣參數(shù),相對于這個(gè)矩陣做縮放效果的疊加
- CATransform3DMakeRotation 旋轉(zhuǎn),3個(gè)參數(shù)分別針對xyz軸進(jìn)行變換。單位是角度,一般使用 M_PI/3. 這種形式
- CATransform3DRotate 旋轉(zhuǎn),增加一個(gè)矩陣參數(shù),相對于這個(gè)矩陣做旋轉(zhuǎn)效果的疊加
下面的demo我把兩個(gè)了layer尺寸改為200*200,錨點(diǎn)使用默認(rèn)值
平移變換

layer2.transform = CATransform3DMakeTranslation(30, 30, 0);
或
CATransform3D transform = CATransform3DIdentity;
transform = CATransform3DTranslate(transform,30,30,0);
layer2.transform = transform;
縮放和旋轉(zhuǎn)疊加變換


CATransform3D transform = CATransform3DIdentity;
transform = CATransform3DRotate(transform, M_PI / 18., 0, 0, 1);
transform = CATransform3DRotate(transform, M_PI / 3., 1, 0, 0);
transform = CATransform3DScale(transform, 0.8, 1.4, 1);
layer2.transform = transform;
CATransform3D transform = CATransform3DIdentity;
transform = CATransform3DRotate(transform, M_PI / 18., 0, 0, 1);
transform = CATransform3DRotate(transform, M_PI / 9., 1, 0, 0);
transform = CATransform3DScale(transform, 0.8, 1.4, 1);
layer2.transform = transform;
這兩段代碼都是現(xiàn)在z軸上旋轉(zhuǎn)10°,然后在x軸上分別旋轉(zhuǎn)60°和30°,并對尺寸做x軸0.8倍和y軸1.4倍的變換。看到兩個(gè)圖差別藍(lán)色的圖層的大小蠻大的,因?yàn)閲@x軸變換相當(dāng)于在屏幕垂直方向旋轉(zhuǎn),所以看到大小變換很大。
修改數(shù)據(jù)結(jié)構(gòu)
修改數(shù)據(jù)結(jié)構(gòu)的方式需要了解矩陣相乘的原理,以下是CATransform3D數(shù)據(jù)結(jié)構(gòu)的定義。可以直接訪問矩陣的成員變量進(jìn)行修改。
struct CATransform3D
{
CGFloat m11, m12, m13, m14;
CGFloat m21, m22, m23, m24;
CGFloat m31, m32, m33, m34;
CGFloat m41, m42, m43, m44;
};
typedef struct CATransform3D CATransform3D;
平移demo的代碼可以修改成如下這種形式
CATransform3D transform = CATransform3DIdentity;
transform.m41 = 30;
transform.m42 = 30;
layer2.transform = transform;
鍵值編碼
鍵值編碼通過關(guān)鍵路徑獲取和設(shè)置一個(gè)圖層的CATransform3D矩陣的值。可以分別通過ratotion,scale,translation和xyz進(jìn)行設(shè)置。
平移demo的代碼可以修改成如下這種形式
[layer2 setValue:[NSNumber numberWithFloat:30] forKeyPath:@"transform.translation.x"];
[layer2 setValue:[NSNumber numberWithFloat:30] forKeyPath:@"transform.translation.y"];
通過上面這些圖層的基礎(chǔ)概念,相信基本可以解決大部分基礎(chǔ)變換效果了~