核心animationCALayer掩盖animationperformance

我们想在我们的iPhone应用程序中使用UITabBar,但有一个例外:我们有一个“同步”button,我想在同步操作发生时旋转。

替代文字

不幸的是,这意味着必须创build一个自定义选项卡栏,但这不是在这里,也不在那里:我使用Core Animation实现的animation看起来很棒。 问题是,虽然animation,它会影响其他一切在屏幕上使用animation的性能:UITableView滚动,MKMapView平移和引脚滴等我的testing设备是iPhone 4。

这个问题似乎是我已经实现了标签栏 – 我想实现与UITabBar非常相似的地方,在那里你只需要为图标提供一个PNG,并且它使用alpha通道来创build正常的和突出显示的状态,通过屏蔽背景图片。 我用CALayer的mask属性完成了这个工作:

 // Inside a UIView subclass' init method... // Create the mask layer by settings its contents as our PNG icon. CALayer *maskLayer = [CALayer layer]; maskLayer.frame = CGRectMake(0, 0, 31, 31); maskLayer.contentsGravity = kCAGravityCenter; maskLayer.contentsScale = [[UIScreen mainScreen] scale]; maskLayer.rasterizationScale = [[UIScreen mainScreen] scale]; maskLayer.contents = (id)symbolImage.CGImage; maskLayer.shouldRasterize = YES; maskLayer.opaque = YES; fgLayer = [[CALayer layer] retain]; fgLayer.frame = self.layer.frame; fgLayer.backgroundColor = [UIColor colorWithImageNamed:@"tabbar-normal-bg.png"].CGColor; fgLayer.mask = maskLayer; // Apply the mask fgLayer.shouldRasterize = YES; fgLayer.opaque = YES; [self.layer addSublayer:fgLayer]; 

(注意:在上面的屏幕截图中,您可以看到我也添加了一个阴影图层,但是为了简单起见,我从代码中删除了该阴影图层,在animation处理时从同步图标中删除阴影图层,所以它不应该是相关的。)

要生成animation,我只需旋转遮罩层:

 - (void)startAnimating { CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath: @"transform"]; CATransform3D transform = CATransform3DMakeRotation(RADIANS(179.9), 0.0, 0.0, 1.0); animation.toValue = [NSValue valueWithCATransform3D:transform]; animation.duration = 5; animation.repeatCount = 10000; animation.removedOnCompletion = YES; [fgLayer.mask addAnimation:animation forKey:@"rotate"]; // Add animation to the mask } 

所以这一切都很好,除了performance。 你可以看到我已经尝试了Google的技巧,关于栅格化图层/使它们变得不透明 – 没有帮助。

我想我已经确定掩模层是罪魁祸首。 当我拿出面具层,只是旋转fgLayer而不是其面具,性能是美好的,但它肯定不是我要去的影响:

替代文字

如果我在fgLayer蒙版旋转fgLayer而不是蒙版性能也与以前一样糟糕。

所以如果不得不重构animation的每一帧都是减速的,那么有什么其他的技巧可以用来实现类似的效果吗? 使用path而不是图像的掩模层? 或者我将不得不下降到OpenGL或什么来获得良好的性能?

更新:进一步强化面具是减速的想法,我的同事build议试图旋转一个CALayer只是图像的内容 – 这样我的例子上面没有面具 – 这样的performance也是如此的好方式。 所以我真的只能做这样一个纯色(没有渐变),但它可能是一个很好的临时解决scheme。 我仍然喜欢旋转一个具有良好性能的面具,所以build议欢迎:)

布伦特,

为什么你需要使用图层蒙版? 你不能只是将你的面具图层转换为子图层吗? 你只需要确保你的图像有适当的alpha值,你可以使用它的CGImageRef作为图层的内容。

还有一件事 我还没有弄清楚为什么,但是我也注意到性能问题时,我应用shouldRasterize在每一层,而不是只有顶层。 您可能会看到如果删除掩码图层中对setShouldRasterize:YES的引用有帮助。

一种方法是创build一个CAShapeLayer作为你的面具 – 你有一个相当一部分的工作,为你做一个带Bézierpath的“同步”图标的版本,但形状层会导致性能成本更低 – 比位图的转换。 不幸的是,你不能确定轮换是性能问题的来源 – 很可能是屏蔽造成的大部分滞后,在这种情况下,你将完成所有的vector化,没有什么好处。

我认为最好的解决scheme是使用UIImage的animationfunction:创build图标旋转animation的每一帧的幻灯片,并简单地在您的标签栏中显示animation的UIImage 。 这不是最优雅的解决scheme,但是整个系统中的许多animation – Mail和Notes垃圾桶 – 可以“删除”图标和各种forms的活动指示符 – 例如 – 都以相同的方式实现。