CAAnimation 与 PerformSelector afterDelay

发布于 2024-12-15 18:16:10 字数 1863 浏览 2 评论 0原文

我正在摆弄一个基本的 CAAnimation 示例,其中我只是想让 CALayer 在 UIView 的子类中旋转。我首先制作一个具有红色背景的新 CALayer 并将其插入到 self.layer 中。然后,我制作一个应该在不透明度更改时触发的 CAAnimation,并将其应用到 CALayer,之后它按预期旋转。

奇怪的是,如果我尝试使用 PerformSelector:withObject:afterDelay: 应用完全相同的动画,CALayer 不再动画,尽管它的不透明度仍然发生变化。更奇怪的是,如果我使用 PerformSelector:withObject:afterDelay: 使用几乎相同的代码对 self.layer 进行动画处理,它就会起作用。

对发生的事情有什么想法吗?这是我的代码:

- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        point = [[CAGradientLayer alloc] init];

        point.backgroundColor = [UIColor redColor].CGColor;
        point.bounds = CGRectMake(0.0f, 0.0f, 30.0f, 20.0f);
        point.position = CGPointMake(100.0f, 100.0f);

        [self.layer addSublayer:point];
        [point release];    

        [self performSelector:@selector(test) withObject:nil afterDelay:2];
    }
    return self;
}

-(void)test {
    [self spinLayer:point];
    // [self spinLayer:self.layer]; works here
}

-(CAAnimation*)animationForSpinning {
    CATransform3D transform;
    transform = CATransform3DMakeRotation(M_PI/2.0, 0, 0, 1.0);

    CABasicAnimation *basicAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
    basicAnimation.toValue = [NSValue valueWithCATransform3D:transform];
    basicAnimation.duration = 5;
    basicAnimation.cumulative = NO;
    basicAnimation.repeatCount = 10000;

    return basicAnimation;
}

-(void)spinLayer:(CALayer*)layer {
    CAAnimation *anim = [self animationForSpinning];
    [layer addAnimation:anim forKey:@"opacity"];
    layer.opacity = 0.6;
}

这是我的界面

@interface MyView : UIView {
    CALayer *point;
}

-(void)test;
-(void)spinLayer:(CALayer*)layer;
-(CAAnimation*)animationForSpinning;

@end

注意:我正在使用应用程序委托中等于 [UIScreen mainScreen].applicationFrame 的框架实例化此视图。

I am messing around with a basic CAAnimation example where Im just trying to get a CALayer to rotate in a subclass of UIView. I start by making a new CALayer with a red background and inserting it into self.layer. I then make a CAAnimation that is supposed to be triggered on opacity changes and apply it to the CALayer, after which it spins as expected.

Weird thing is that if I try to apply the exact same animation using performSelector:withObject:afterDelay:, the CALayer no longer animates, although its opacity still changes. Even weirder is that if I use performSelector:withObject:afterDelay: to animate self.layer using pretty much the same code, it works.

Any ideas as to what's going on? Here is my code:

- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        point = [[CAGradientLayer alloc] init];

        point.backgroundColor = [UIColor redColor].CGColor;
        point.bounds = CGRectMake(0.0f, 0.0f, 30.0f, 20.0f);
        point.position = CGPointMake(100.0f, 100.0f);

        [self.layer addSublayer:point];
        [point release];    

        [self performSelector:@selector(test) withObject:nil afterDelay:2];
    }
    return self;
}

-(void)test {
    [self spinLayer:point];
    // [self spinLayer:self.layer]; works here
}

-(CAAnimation*)animationForSpinning {
    CATransform3D transform;
    transform = CATransform3DMakeRotation(M_PI/2.0, 0, 0, 1.0);

    CABasicAnimation *basicAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
    basicAnimation.toValue = [NSValue valueWithCATransform3D:transform];
    basicAnimation.duration = 5;
    basicAnimation.cumulative = NO;
    basicAnimation.repeatCount = 10000;

    return basicAnimation;
}

-(void)spinLayer:(CALayer*)layer {
    CAAnimation *anim = [self animationForSpinning];
    [layer addAnimation:anim forKey:@"opacity"];
    layer.opacity = 0.6;
}

and this is my interface

@interface MyView : UIView {
    CALayer *point;
}

-(void)test;
-(void)spinLayer:(CALayer*)layer;
-(CAAnimation*)animationForSpinning;

@end

Note: I am instantiating this view with a frame equal to [UIScreen mainScreen].applicationFrame from within the app delegate.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

挽容 2024-12-22 18:16:10

将其更改

[layer addAnimation:anim forKey:@"opacity"];

为:

[layer addAnimation:anim
             forKey:@"notOpacity!"];

发生的情况是隐式动画 layer.opacity = 0.6 会覆盖显式动画。发生这种情况是因为核心动画在添加隐式动画时使用属性名称。

(如果将 layer.opacity = 0.6 移至 [layer addAnimation:anim forKey:@"opacity"]; 上方,它也可以工作,但是 layer.opacity< /code> 不会获得动画效果。)

以及为什么它可以毫不延迟地工作:因为只有当图层位于树中并已显示时,隐式动画才会“启用”。

Change this:

[layer addAnimation:anim forKey:@"opacity"];

into this:

[layer addAnimation:anim
             forKey:@"notOpacity!"];

What happens is that implicit animation layer.opacity = 0.6 overwrites you explicit animation. This happens because Core Animation uses property names when adding implicit animations.

(If you move layer.opacity = 0.6 above [layer addAnimation:anim forKey:@"opacity"]; it will also work, but layer.opacity will not get animated.)

And why it works without delay: because implicit animations are "enabled" only if layer is in the tree and been displayed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文