首页 文章

核心动画CALayer面具动画表现

提问于
浏览
20

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

alt text

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

问题似乎是我如何've implemented the tab bar - I wanted to achieve something very similar to UITabBar, where you just supply a PNG for the icon and it uses the alpha channel to create the normal and highlighted states by masking a background image. I accomplished this with CALayer' s 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];

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

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

- (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
}

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

我想我已经确定掩模层是罪魁祸首 . 当我取出遮罩层并只旋转 fgLayer 而不是它的遮罩时,性能非常好,尽管它是's certainly not the affect I' m:

alt text

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

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

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

2 回答

  • 7

    布伦特,

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

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

  • 15

    一种方法是创建一个 CAShapeLayer 用作你的面具 - 你要确保旋转是性能问题的来源 - 它很可能是导致大部分延迟的屏蔽,在这种情况下你会做了所有那些矢量化的好处 .

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

相关问题