当 CABasicAnimation 应该只为一件事制作动画时,它会为所有内容制作动画

Posted

技术标签:

【中文标题】当 CABasicAnimation 应该只为一件事制作动画时,它会为所有内容制作动画【英文标题】:CABasicAnimation animates everything when it should only animate one thing 【发布时间】:2010-06-22 01:36:18 【问题描述】:

我制作了一堆单独的小图片,每张图片都有一个单独的 CALayer,它们应该以不同的速率异步淡入和淡出。每个都有一个背景子层和一个填充子层。计时器在后台运行,以在特定时刻单独为每个人设置动画。对于程序的当前行为,它不是为每个单独的行为设置动画,而是围绕它设置整个屏幕的动画。您能帮我制作它,以便一次只为一张图像设置动画吗?

编辑:我应该更清楚。时机不是问题。在我切换到 CoreAnimation 之前,这些图像会在适当的时间正确地进行动画处理。但这里的主要问题是,当我告诉一个图像进行动画处理时,整个屏幕,包括所有图像之外的屏幕背景部分,都会被动画化。

以下代码段用于在 UIView 代码中创建分层结构。 Self 指的是主 UIView。返回值用于为代表屏幕上这些小图像之一的类设置 CALayer 成员变量。

- (CALayer *) createImageLayer:(CGPoint)orig Center:(CGPoint)pos 
    CALayer *parentLayer = [self layer];
    CALayer *childLayer1 = [CALayer layer];
    childLayer1.bounds = CGRectMake(0, 0, 40.0f, 40.0f);
    childLayer1.position = pos;
    CALayer *childLayer2 = [CALayer layer];
    childLayer2.bounds = CGRectMake(0, 0, 40.0f, 40.0f);
    childLayer2.position = pos;

    float components[4] = 1.0, 1.0, 1.0, 1.0;

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGColorRef whiteColor = CGColorCreate( colorSpace, components);

    childLayer1.backgroundColor = whiteColor;
    childLayer2.backgroundColor = whiteColor;

    UIImage *childImage = [UIImage imageNamed:@"back.png"];
    UIImage *childImage2 = [UIImage imageNamed:@"fill.png"];

    CGImageRef imageRef = [childImage CGImage];
    CGImageRef imageRef2 = [childImage2 CGImage];

    childLayer1.contents=(id)imageRef;
    childLayer2.contents=(id)imageRef2;

    [parentLayer addSublayer:childLayer1];
    [parentLayer addSublayer:childLayer2];

    CGColorSpaceRelease(colorSpace);
    CGColorRelease(whiteColor);

    return parentLayer;

告诉它动画的代码。图像对象被告知将动画添加到其图层成员。

- (void) fadeAnimation:(ImageClass *)image 
    CABasicAnimation *theAnimation;

    theAnimation=[CABasicAnimation animationWithKeyPath:@"opacity"];
    theAnimation.duration=1.0; // fixed duration for now
    theAnimation.repeatCount=1;
    theAnimation.autoreverses=YES;
    theAnimation.fromValue=[NSNumber numberWithFloat:1.0];
    theAnimation.toValue=[NSNumber numberWithFloat:0.0];
    [image.myLayer addAnimation:theAnimation forKey:@"animateOpacity"];

【问题讨论】:

【参考方案1】:

首先,您的代码可以显着压缩,使其更易于阅读:

- (CALayer *) createImageLayer:(CGPoint)orig Center:(CGPoint)pos 
    
    CALayer *childLayer1 = [CALayer layer];
    childLayer1.bounds = CGRectMake(0, 0, 40.0f, 40.0f);
    childLayer1.position = pos;

    CALayer *childLayer2 = [CALayer layer];
    childLayer2.bounds = CGRectMake(0, 0, 40.0f, 40.0f);
    childLayer2.position = pos;

    childLayer1.backgroundColor = [[UIColor whiteColor] CGColor];
    childLayer2.backgroundColor = [[UIColor whiteColor] CGColor];

    childLayer1.contents=(id)[[UIImage imageNamed:@"back.png"] CGImage];
    childLayer2.contents=(id)[[UIImage imageNamed:@"fill.png"] CGImage];

    [[self layer] addSublayer:childLayer1];
    [[self layer] addSublayer:childLayer2];

    return parentLayer;

接下来,我建议您不要创建计时器,而只需使用 -performSelector:withObject:afterDelay。然后,您可以一次添加所有动画,只需错开 afterDelay 参数即可。像这样的:

int i = 0;
for (i = 0; i < 10; ++i)

    [self performSelector:@selector(fadeAnimation:) 
               withObject:images[i] 
               afterDelay:(CGFloat)i];

其中 images 是 ImageClass 对象的 C 数组。当然,您不必使用 C 数组。您可以使用 NSArray,但您的 afterDelay 参数仍然需要一个计数器。这将使您的动画错开每一秒发生一次。我不确定你到底想要什么,所以我只是举个例子。

Core Animation 还有其他方法可以满足您的要求。你可以看看动画分组和 beginTime 属性,但我认为我上面提到的 -peformSelector 方法是阻力较小的路径。

最好的问候

【讨论】:

感谢您的帮助。我遇到的主要问题是,当我认为我要告诉每个单独的图像进行淡入淡出动画时,例如 [self fadeAnimation:myImage],它反而对整个屏幕而不是图像进行动画处理。时间对我来说并不是真正的问题,但我可以试试你的建议,因为这似乎比计时器更适合我的目的。

以上是关于当 CABasicAnimation 应该只为一件事制作动画时,它会为所有内容制作动画的主要内容,如果未能解决你的问题,请参考以下文章

在情节提要中,您可以只为一台设备编辑布局吗?

我只为一瓶啤酒

Rails 6.0 在为一种用户创建和更新时验证密码是不是存在,但只为另一种用户更新

为啥当我为我的 CABasicAnimation 设置低持续时间值时它会跳跃?

当 CABasicAnimation 正在制作动画时,我该如何回调?

PHP - 接受多个支付网关