核心动画CALayer面具动画表现

Bre*_*ham 20 iphone core-animation objective-c calayer ios

我们想在我们的iPhone应用程序中使用UITabBar,但有一个例外:我们有一个"同步"按钮,我想在同步操作发生时旋转.

替代文字

不幸的是,这意味着必须创建一个自定义标签栏,但这既不在这里也不在那里:我使用Core Animation实现的动画看起来很棒.问题是,在制作动画时,它会对屏幕上使用动画的其他所有内容产生不利影响:UITableView滚动,MKMapView平移和引脚丢弃等.我的测试设备是iPhone 4.

问题似乎是我如何实现标签栏 - 我想要实现与UITabBar非常相似的东西,你只需要为图标提供PNG,它使用alpha通道通过屏蔽背景来创建正常和突出显示的状态图片.我用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];
Run Code Online (Sandbox Code Playgroud)

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

要设置动画,我只需旋转遮罩层:

- (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
}
Run Code Online (Sandbox Code Playgroud)

所以这一切都很有效,除了性能.你可以看到我已经尝试过关于栅格化图层/使它们变得不透明的技巧,但是没有帮助.

我想我已经确定掩模层是罪魁祸首.当我拿出面具层而只是旋转fgLayer而不是它的面具时,性能很棒,虽然它肯定不是我想要的影响:

替代文字

如果fgLayer在应用蒙版旋转而不是蒙版,性能也和以前一样糟糕.

因此,如果必须重新组合掩模,动画的每一帧都会变慢,那么我是否可以使用其他任何技术来实现类似的效果,从而获得更好的性能?使用路径而不是图像作为遮罩层?或者我将不得不下载OpenGL或其他什么来获得良好的性能?

更新:进一步加强了面具减速的想法,我的同事建议尝试用图像作为内容来旋转CALayer - 这与我上面的w/o面具示例相似 - 并且性能也很好.所以我真的只能做那样的纯色(没有渐变),但它可能是一个很好的临时解决方案.我仍然喜欢旋转具有良好性能的面膜,所以建议欢迎:)

Mat*_*ong 15

布伦特,

为什么需要使用图层蒙版?你不能只是将你的掩码层转换为子层吗?您只需要确保您的图像具有正确的alpha,并且您将使用它的CGImageRef作为该图层的内容.

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


Noa*_*oon 7

一种方法是创建一个CAShapeLayer用作面具的方法 - 你可以通过Bézier路径制作一个"同步"图标版本,但是形状图层的性能成本要低得多 -转换比位图的转换.不幸的是,你无法确定旋转是性能问题的来源 - 它很可能是导致大部分延迟的屏蔽,在这种情况下,你将完成所有的矢量化以获得很少的好处.

我认为最好的解决方案是使用UIImage动画功能:创建图标旋转动画的每一帧的幻灯片,并UIImage在标签栏中显示动画.这不是最优雅的解决方案,但系统中的一些动画 - 邮件和便笺垃圾 - 可以"删除"图标和各种形式的活动指示器 - 例如 - 以相同的方式实现.

  • 谢谢你的回答 - 使用动画的幻灯片肯定是我正在考虑的事情,但听起来像很多工作+文件空间.幸运的是,*superlayer*上的`shouldRasterize`似乎达到了我预期的性能. (2认同)