前言
不知你是否遇到過將CALayer旋轉(zhuǎn)360度的需求,如果有的話坛猪,你也許會(huì)嘗試使用transform做旋轉(zhuǎn)動(dòng)畫脖阵,然后發(fā)現(xiàn)。墅茉。命黔。CALayer根本就不動(dòng)。本文將深入解釋并解決這個(gè)問題躁锁。
transform.rotation
CABasicAnimation
支持transform.rotation
這個(gè)keyPath纷铣,你可以將這個(gè)值從0改變到2pi進(jìn)行動(dòng)畫卵史。transform.rotation
是繞z軸旋轉(zhuǎn)战转。當(dāng)然你也可以指定繞哪個(gè)軸旋轉(zhuǎn),比如x軸就是transform.rotation.x
以躯。這個(gè)可動(dòng)畫屬性能夠完美的實(shí)現(xiàn)旋轉(zhuǎn)360度的需求槐秧。那么問題來了,既然它可以忧设,為什么我這么寫就不可以呢刁标?我也是從0度的transform到360度的transform呀。
CATransform3D start = CATransform3DMakeRotation(0 * M_PI / 180.0, 0, 0, 1);
CATransform3D end = CATransform3DMakeRotation(2 * M_PI / 180.0, 0, 0, 1);
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"];
animation.fromValue = [NSValue valueWithCATransform3D:start];
animation.toValue = [NSValue valueWithCATransform3D:end];
animation.duration = 3.3;
動(dòng)畫插值
我們知道動(dòng)畫要想平滑址晕,就得在我們給的from和to之間進(jìn)行插值然后渲染這些插值情況下的幀膀懈。那么這些值是怎么插的呢?我們可以自定義一個(gè)Animatable的屬性看看谨垃。下面是自定義Animatable的rotateX
屬性需要的代碼启搂。
@implementation HTCardLayer
- (void)setRotateX:(CGFloat)rotateX {
_rotateX = rotateX;
CATransform3D transform = CATransform3DIdentity;
transform.m34 = 1.0 / -300.0;
self.transform = CATransform3DRotate(transform, rotateX, 1, 0, 0);
}
- (void)display {
CGFloat rotateX = [(HTCardLayer *)self.presentationLayer rotateX];
NSLog(@"%lf", rotateX);
CATransform3D transform = CATransform3DIdentity;
transform.m34 = 1.0 / -300.0;
self.transform = CATransform3DRotate(transform, rotateX, 1, 0, 0);
}
+ (BOOL)needsDisplayForKey:(NSString *)key {
if ([key isEqualToString:@"rotateX"]) {
return YES;
}
return [super needsDisplayForKey:key];
}
@end
needsDisplayForKey
告訴系統(tǒng)rotateX
修改后需要刷新顯示,display
則負(fù)責(zé)刷新顯示刘陶,因?yàn)楸粍?dòng)畫的屬性值都在presentationLayer
中胳赌,所以我們從presentationLayer
中取rotateX
的最新值。下面是動(dòng)畫過程中打印出來的rotateX
的值匙隔∫缮唬基本就是一個(gè)線性的變化過程,因?yàn)槲覜]有設(shè)置任何時(shí)間函數(shù)纷责。rotateX
是一個(gè)CGFloat捍掺,那如果是CATransform3D呢?會(huì)怎么變化再膳?
0.352071
0.730180
1.101104
1.477982
1.833467
2.189324
2.550581
2.915682
3.273214
3.649389
4.013420
4.376663
4.740999
5.113640
5.483836
5.861515
6.234217
CATransform3D的插值
我新增了一個(gè)Animatable的屬性customMatrix
來查看CATransform3D類型的屬性是如何插值的挺勿。CATransform3D其實(shí)是一個(gè)4x4的矩陣。
- (void)display {
CGFloat rotateX = [(HTCardLayer *)self.presentationLayer rotateX];
CATransform3D customMatrix = [(HTCardLayer *)self.presentationLayer customMatrix];
// NSLog(@"%lf", rotateX);
NSLog(@"%lf, %lf, %lf, %lf", customMatrix.m11, customMatrix.m12, customMatrix.m13, customMatrix.m14);
NSLog(@"%lf, %lf, %lf, %lf", customMatrix.m21, customMatrix.m22, customMatrix.m23, customMatrix.m24);
NSLog(@"%lf, %lf, %lf, %lf", customMatrix.m31, customMatrix.m32, customMatrix.m33, customMatrix.m34);
NSLog(@"%lf, %lf, %lf, %lf", customMatrix.m41, customMatrix.m42, customMatrix.m43, customMatrix.m44);
NSLog(@"---------");
CATransform3D transform = CATransform3DIdentity;
transform.m34 = 1.0 / -300.0;
self.transform = CATransform3DRotate(transform, rotateX, 1, 0, 0);
}
+ (BOOL)needsDisplayForKey:(NSString *)key {
if ([key isEqualToString:@"rotateX"]) {
return YES;
}
if ([key isEqualToString:@"customMatrix"]) {
return YES;
}
return [super needsDisplayForKey:key];
}
下面是部分?jǐn)?shù)據(jù)饵史,我用的是繞z軸旋轉(zhuǎn)的矩陣满钟,所以只有m11,m12,m21,m22
有數(shù)據(jù)胜榔,其他都是Identity矩陣的基本數(shù)值∨确可以看出m11,m12,m21,m22
也是各自呈線性變化夭织。
0.982547, -0.186012, 0.000000, 0.000000
0.186012, 0.982547, 0.000000, 0.000000
0.000000, 0.000000, 1.000000, 0.000000
0.000000, 0.000000, 0.000000, 1.000000
---------
0.930553, -0.366158, 0.000000, 0.000000
0.366158, 0.930553, 0.000000, 0.000000
0.000000, 0.000000, 1.000000, 0.000000
0.000000, 0.000000, 0.000000, 1.000000
---------
0.830170, -0.557510, 0.000000, 0.000000
0.557510, 0.830170, 0.000000, 0.000000
0.000000, 0.000000, 1.000000, 0.000000
0.000000, 0.000000, 0.000000, 1.000000
---------
0.700345, -0.713804, 0.000000, 0.000000
0.713804, 0.700345, 0.000000, 0.000000
0.000000, 0.000000, 1.000000, 0.000000
0.000000, 0.000000, 0.000000, 1.000000
---------
0.560556, -0.828117, 0.000000, 0.000000
0.828117, 0.560556, 0.000000, 0.000000
0.000000, 0.000000, 1.000000, 0.000000
0.000000, 0.000000, 0.000000, 1.000000
---------
0.403126, -0.915145, 0.000000, 0.000000
0.915145, 0.403126, 0.000000, 0.000000
0.000000, 0.000000, 1.000000, 0.000000
0.000000, 0.000000, 0.000000, 1.000000
---------
0.221203, -0.975228, 0.000000, 0.000000
0.975228, 0.221203, 0.000000, 0.000000
0.000000, 0.000000, 1.000000, 0.000000
0.000000, 0.000000, 0.000000, 1.000000
---------
0.030679, -0.999529, 0.000000, 0.000000
0.999529, 0.030679, 0.000000, 0.000000
0.000000, 0.000000, 1.000000, 0.000000
0.000000, 0.000000, 0.000000, 1.000000
---------
-0.158010, -0.987438, 0.000000, 0.000000
0.987438, -0.158010, 0.000000, 0.000000
0.000000, 0.000000, 1.000000, 0.000000
0.000000, 0.000000, 0.000000, 1.000000
---------
-0.347984, -0.937500, 0.000000, 0.000000
0.937500, -0.347984, 0.000000, 0.000000
0.000000, 0.000000, 1.000000, 0.000000
0.000000, 0.000000, 0.000000, 1.000000
---------
-0.517222, -0.855851, 0.000000, 0.000000
0.855851, -0.517222, 0.000000, 0.000000
0.000000, 0.000000, 1.000000, 0.000000
0.000000, 0.000000, 0.000000, 1.000000
---------
-0.672144, -0.740421, 0.000000, 0.000000
0.740421, -0.672144, 0.000000, 0.000000
0.000000, 0.000000, 1.000000, 0.000000
0.000000, 0.000000, 0.000000, 1.000000
---------
-0.812617, -0.582798, 0.000000, 0.000000
0.582798, -0.812617, 0.000000, 0.000000
0.000000, 0.000000, 1.000000, 0.000000
0.000000, 0.000000, 0.000000, 1.000000
---------
-0.905049, -0.425307, 0.000000, 0.000000
0.425307, -0.905049, 0.000000, 0.000000
0.000000, 0.000000, 1.000000, 0.000000
0.000000, 0.000000, 0.000000, 1.000000
---------
-0.969663, -0.244444, 0.000000, 0.000000
0.244444, -0.969663, 0.000000, 0.000000
0.000000, 0.000000, 1.000000, 0.000000
0.000000, 0.000000, 0.000000, 1.000000
---------
-0.998409, -0.056390, 0.000000, 0.000000
0.056390, -0.998409, 0.000000, 0.000000
0.000000, 0.000000, 1.000000, 0.000000
0.000000, 0.000000, 0.000000, 1.000000
---------
這也就解釋了為什么0到360度的動(dòng)畫直接不執(zhí)行了,因?yàn)?和360度的矩陣一模一樣吠撮,也就無法計(jì)算出任何插值尊惰。
總結(jié)
總而言之,如果你想360度旋轉(zhuǎn)CALayer泥兰,要么使用transform.rotation
弄屡,要么就自定義Animatable的屬性。