iOS优雅的将CALayer旋转360度示例代码
什么是CALayer
*在iOS系统中,你能看得见摸得着的东西基本上都是UIView,比如一个按钮、一个文本标签、一个文本输入框、一个图标等等,这些都是UIView。
*其实UIView之所以能显示在屏幕上,完全是因为它内部的一个层。
*在创建UIView对象时,UIView内部会自动创建一个层(即CALayer对象),通过UIView的layer属性可以访问这个层。当UIView需要显示到屏幕上时,会调用drawRect:方法进行绘图,并且会将所有内容绘制在自己的层上,绘图完毕后,系统会将层拷贝到屏幕上,于是就完成了UIView的显示。
*换句话说,UIView本身不具备显示的功能,是它内部的层才有显示功能。
引言
不知你是否遇到过将CALayer旋转360度的需求,如果有的话,你也许会尝试使用transform做旋转动画,然后发现。。。CALayer根本就不动。本文将深入解释并解决这个问题。
transform.rotation
CABasicAnimation支持transform.rotation这个keyPath,你可以将这个值从0改变到2pi进行动画。transform.rotation是绕z轴旋转。当然你也可以指定绕哪个轴旋转,比如x轴就是transform.rotation.x。这个可动画属性能够完美的实现旋转360度的需求。那么问题来了,既然它可以,为什么我这么写就不可以呢?我也是从0度的transform到360度的transform呀。
CATransform3Dstart=CATransform3DMakeRotation(0*M_PI/180.0,0,0,1); CATransform3Dend=CATransform3DMakeRotation(2*M_PI/180.0,0,0,1); CABasicAnimation*animation=[CABasicAnimationanimationWithKeyPath:@"transform"]; animation.fromValue=[NSValuevalueWithCATransform3D:start]; animation.toValue=[NSValuevalueWithCATransform3D:end]; animation.duration=3.3;
动画插值
我们知道动画要想平滑,就得在我们给的from和to之间进行插值然后渲染这些插值情况下的帧。那么这些值是怎么插的呢?我们可以自定义一个Animatable的属性看看。下面是自定义Animatable的rotateX属性需要的代码。
@implementationHTCardLayer -(void)setRotateX:(CGFloat)rotateX{ _rotateX=rotateX; CATransform3Dtransform=CATransform3DIdentity; transform.m34=1.0/-300.0; self.transform=CATransform3DRotate(transform,rotateX,1,0,0); } -(void)display{ CGFloatrotateX=[(HTCardLayer*)self.presentationLayerrotateX]; NSLog(@"%lf",rotateX); CATransform3Dtransform=CATransform3DIdentity; transform.m34=1.0/-300.0; self.transform=CATransform3DRotate(transform,rotateX,1,0,0); } +(BOOL)needsDisplayForKey:(NSString*)key{ if([keyisEqualToString:@"rotateX"]){ returnYES; } return[superneedsDisplayForKey:key]; } @end
needsDisplayForKey告诉系统rotateX修改后需要刷新显示,display则负责刷新显示,因为被动画的属性值都在presentationLayer中,所以我们从presentationLayer中取rotateX的最新值。下面是动画过程中打印出来的rotateX的值。基本就是一个线性的变化过程,因为我没有设置任何时间函数。rotateX是一个CGFloat,那如果是CATransform3D呢?会怎么变化?
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的插值
我新增了一个Animatable的属性customMatrix来查看CATransform3D类型的属性是如何插值的。CATransform3D其实是一个4x4的矩阵。
-(void)display{ CGFloatrotateX=[(HTCardLayer*)self.presentationLayerrotateX]; CATransform3DcustomMatrix=[(HTCardLayer*)self.presentationLayercustomMatrix]; //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(@"---------"); CATransform3Dtransform=CATransform3DIdentity; transform.m34=1.0/-300.0; self.transform=CATransform3DRotate(transform,rotateX,1,0,0); } +(BOOL)needsDisplayForKey:(NSString*)key{ if([keyisEqualToString:@"rotateX"]){ returnYES; } if([keyisEqualToString:@"customMatrix"]){ returnYES; } return[superneedsDisplayForKey:key]; }
下面是部分数据,我用的是绕z轴旋转的矩阵,所以只有m11,m12,m21,m22有数据,其他都是Identity矩阵的基本数值。可以看出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度的动画直接不执行了,因为0和360度的矩阵一模一样,也就无法计算出任何插值。
总结
总而言之,如果你想360度旋转CALayer,要么使用transform.rotation,要么就自定义Animatable的属性。
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。