欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

iOS优雅的将CALayer旋转360度示例代码

程序员文章站 2023-12-19 12:20:10
什么是calayer * 在ios系统中,你能看得见摸得着的东西基本上都是uiview,比如一个按钮、一个文本标签、一个文本输入框、一个图标等等,这些都是uiview。...

什么是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呀。

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;

动画插值

我们知道动画要想平滑,就得在我们给的from和to之间进行插值然后渲染这些插值情况下的帧。那么这些值是怎么插的呢?我们可以自定义一个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告诉系统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 {
 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];
}

下面是部分数据,我用的是绕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的属性。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。

上一篇:

下一篇: