核心动画和视图旋转性能不佳:如何改进?
我有 12 个视图,当通过触摸图标几秒钟进入主屏幕自定义模式时,我旋转的视图几乎与主屏幕中的图标类似。
我使用 3D 变换代码来进行旋转。 它们的持续时间仅为 0.02 秒,并且旋转的角度和方向会根据加速度测量而永久改变。
其中 5 个视图表现良好,但 12 个视图的性能非常糟糕。 这是旋转代码:
CATransform3D rotatedTransform = CATransform3DRotate(CATransform3DIdentity, degrees * M_PI / 180.0, 0.0f, 0.0f, 1.0f);
self.layer.transform = rotatedTransform;
周围有一些核心动画。 但我发现这里浪费了 CPU,因为我不做任何 3D 的事情。 我真的只旋转 2D,没有其他。 它们是简单的 UIImageViews,但是一个自定义类,可以自行执行旋转动画。
我听说有“仿射”变换应该适用于二维空间。 在这种情况下,您建议将其更改为 2D 吗?
我必须更喜欢更改图层或视图的变换吗? 哪个更快?
I have 12 views which I rotate almost similar to the icons in the home screen when going into homescreen-customization-mode by touching an icon for a few seconds.
I use a 3D transformation code to do the rotations. They have each a duration of just 0.02 seconds, and the angle and direction of rotation changes permanently upon acceleration measurements.
5 of those views are fine, but 12 have a very bad performance. Here's the rotation code:
CATransform3D rotatedTransform = CATransform3DRotate(CATransform3DIdentity, degrees * M_PI / 180.0, 0.0f, 0.0f, 1.0f);
self.layer.transform = rotatedTransform;
there's some core animation wrapped around it. But I see a waste of CPU here, since I don't do any 3D stuff. I really only rotate 2D and nothing else. They're simple UIImageViews, but a custom class that does this rotation animations on her own.
I've heared that there are "affine" transforms which are supposed to work for the 2D space. Would you advise to change that to 2D in this case?
Must I prefer to change the transform of the layer, or of the view? which is faster?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
Shark it。您必须知道到底什么是继续缓慢的。
尝试将更新间隔从 0.02 秒增加到 0.1 秒左右; 这是可以接受的吗?
如果所有图像一起旋转,请在超级层上使用
sublayerTransform
而不是单独转换每个图像尝试关闭动画,只是为了确认您的回调按预期工作(setDisableActions:在 CATransaction 上)。 当您关闭它们时,您是否看到与 Shark 中的缓慢相同的情况?
如果您在滚动视图中执行此操作,则可能会遇到其他问题。 您需要处理屏幕上/屏幕外的事情等。
据我所知,3d 变换与核心动画中的仿射变换的速度相同。 基本的正弦/余弦内容不会减慢应用程序
有关您想要实现的实际效果的更多信息确实有助于提高性能。
屏幕上的图像有多大?
Shark it. You must know what exactly is slow to continue.
Try increasing that update interval from 0.02s to something like 0.1s; is that acceptable?
If all of the images are being rotated together, use a
sublayerTransform
on the super-layer instead of transforming each individuallyTry it w/o animations off, just to confirm that your callbacks are working as you expect (setDisableActions: on CATransaction). Do you see the same things as being slow in Shark when you have them off?
If you're doing this inside a scroll view, you might have other problems. You'll need to take care of things going on/off screen, etc.
3d transforms are the same speed as affine ones in core animation AFAIK. basic sin/cos stuff isn't slowing down the app
More information about the actual effect you're trying to achieve would really help to improve performance.
How big on screen are the images?
CALayer 旋转是硬件加速的,2D 和 3D 变换非常相似,不会发生重绘,不需要转到 opengl,不需要缓存。
Shark 会有所帮助,但您需要知道您在寻找什么,并且您正在寻找的不是提高当前代码的性能,而是完全删除您的代码。
听起来你为了改变每一层的角度而经常检查自己的代码。 当您让 CA 完成工作时您就赢了。
因此,这里的策略是找到一种方法让 CA 完成工作,并且每秒给您回电的次数少于 50 次。
一个
CAAnimationGroup
为每个图层包含一些CAPropertyAnimation
并设置一次一秒的动画怎么样?一旦您将其交给 CA,CA 就会在自己的线程中播放它。
CALayer rotations are hardware accelerated, 2D and 3D transforms would be pretty similar, no redraws are happening, no need to go to opengl, no need to cache.
Shark would help, but you would need to know what you are looking for, and what you're looking for is not improving the performance of your current code, but removing your code completely.
Sounds like you are going through your own code waaay too often, for the purpose of changing the angle of each layer. You win when you let CA do the work.
So the strategy here is to find a way to have CA do the work, and call you back less than 50 times a second.
How about a
CAAnimationGroup
containing a fewCAPropertyAnimation
for each of your layers and setting up, say, one second of animation at a time?Once you hand that off to CA, CA will playing it back in its own thread.
我的建议是使用 OpenGL ES。
尽管核心动画比“UITransformations”更快一点,但您面临的问题是一个经典问题:您试图创建基于帧到帧的动作,其中有大量“虚拟”精灵漂浮在周围。 这不是 UIKit 的用途。 尤其是您想要制作的动画。 旋转需要三角学来计算像素插值。 这是一个相当昂贵的过程。
除非对动画强度、同时动画的对象数量以及重新计算新变换的频率有明确的限制,否则我目前给您的唯一建议是OpenGL ES。
迄今为止我使用 iPhone 的体验非常相似。 每次我们给应用程序添加果汁时,当前的平台都无法处理它。 我们最终使用了 OpenGL ES,它值得学习。 性能令人难以置信。
对于这个“坏消息”,我深感抱歉,但是我强烈建议不要在基于帧到帧的应用程序中使用 UIKit 和 Core Animation。
My advice is to go OpenGL ES.
Although Core Animation is a tad snappier than "UITransformations", the problem you're facing is a classic one: you're trying to create frame to frame based action with lots of "virtual" sprites floating around. That is not what UIKit is meant to be used for. Especially the animations you're trying to do. Rotation requires trigonometry in order to calculate pixel interpolation. That's quite an expensive procedure.
Unless there are clear restrictions to the intensitivity of the animation, the number of objects animation at the same time, and the frequency of recalculating new transformations, my only advice for you at this point is OpenGL ES.
My experience thus far with the iPhone has been quite alike. Every time we juiced up the app, the current platform could not handle it. We ended up using OpenGL ES, and it's worth the learning curve. The performance is incredible.
I'm sorry for the "bad news", but I strongly advise against using UIKit and Core Animation for frame to frame based apps.
听起来你不断地重新描绘你的观点。 我确信有一种方法可以禁用此功能,并且仅在动画结束时重绘。
It sounds like your redrawing your views constantly. I'm sure there is a way to disable this and only redraw at the end of the animation.