如何让CAAnimation在每个动画节目中调用块? [英] How can I get a CAAnimation to call a block every animation tick?

查看:123
本文介绍了如何让CAAnimation在每个动画节目中调用块?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我可以以某种方式在CAAnimation的每个tick上执行一个块吗?它可能像下面的代码一样工作。如果有一种方法可以使用选择器,那也可以。

Can I somehow have a block execute on every "tick" of a CAAnimation? It could possibly work like the code below. If there's a way to do this with a selector, that works too.

NSString* keyPath = @"position.x";
CGFloat endValue = 100;

[CATransaction setDisableActions:YES];
[self.layer setValue:@(toVal) forKeyPath:keyPath];

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:keyPath];
animation.duration = 1;
animation.delegate = self;

__weak SelfClass* wself = self;
animation.eachTick = ^{
    NSLog(@"Current x value: %f", [wself valueForKeyPath:keypath]);
};

[self.layer addAnimation:animation forKey:nil];


推荐答案

典型的技术是使用显示链接( CADisplayLink )。

The typical technique is to employ a display link (CADisplayLink).

因此,为显示链接定义一个属性:

So, define a property for the display link:

@property (nonatomic, strong) CADisplayLink *displayLink;

然后实现启动,停止和处理显示链接的方法:

And then implement the methods to start, stop, and handle the display link:

- (void)startDisplayLink
{
    self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleDisplayLink:)];
    [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
}

- (void)stopDisplayLink
{
    [self.displayLink invalidate];
    self.displayLink = nil;
}

- (void)handleDisplayLink:(CADisplayLink *)displayLink
{
    CALayer *layer = self.animatedView.layer.presentationLayer;

    NSLog(@"%@", NSStringFromCGRect(layer.frame));
}

注意,虽然视图是动画,但您无法查看其基本属性(因为它会反映最终目的地而不是飞行中位置),而是您访问动画视图的图层 presentationLayer ,如上所示。

Note, while a view is animating, you cannot look at its basic properties (because it will reflect the end destination rather than the "in flight" position), but rather you access the animated view's layer's presentationLayer, as shown above.

无论如何,在开始动画时启动显示链接。并在完成后将其删除。

Anyway, start the display link when you start your animation. And remove it upon completion.

使用标准的基于块的动画,您可以执行以下操作:

With standard block-based animation, you'd do something like:

[UIView animateWithDuration:2.0 delay:0 options:0 animations:^{
    view.frame = someNewFrame;
} completion:^(BOOL finished) {
    [self stopDisplayLink];
}];

[self startDisplayLink];

使用Core Animation,它可能看起来像:

With Core Animation, it might look like:

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
animation.fromValue = [NSValue valueWithCGPoint:startPoint];
animation.toValue = [NSValue valueWithCGPoint:endPoint];

[CATransaction setAnimationDuration:1.0];
[CATransaction setCompletionBlock:^{
    [self stopDisplayLink];
}];

[CATransaction begin];
[self.animatedView.layer addAnimation:animation forKey:nil];
[CATransaction commit];

[self startDisplayLink];

这篇关于如何让CAAnimation在每个动画节目中调用块?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆