核心动画进度回调 [英] Core animation progress callback

查看:138
本文介绍了核心动画进度回调的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当核心动画在运行时达到某些点时(例如,完成时的50%和66%?

Is there an easy way to be called back when a Core Animation reaches certain points as it's running (for example, at 50% and 66% of completion ?

),是否有一种简单的方法可以回叫我正在考虑设置NSTimer,但这并不像我想的那么准确。

I'm currently thinking about setting up an NSTimer, but that's not really as accurate as I'd like.

推荐答案

我'我终于为这个问题开发了一个解决方案。

I've finally developed a solution for this problem.

基本上我希望每一帧都能回电话,做我需要做的事。

Essentially I wish to be called back for every frame and do what I need to do.

没有明显的方法来观察动画的进展,但实际上它是可能的:

There's no obvious way to observe the progress of an animation, however it is actually possible:


  • 首先,我们需要创建一个新的CALayer子类,它具有一个名为'progress'的动画属性。

  • Firstly we need to create a new subclass of CALayer that has an animatable property called 'progress'.

我们将图层添加到树中,然后创建一个在动画持续时间内将进度值从0驱动到1的动画。

We add the layer into our tree, and then create an animation that will drive the progress value from 0 to 1 over the duration of the animation.

由于我们的progress属性可以设置动画,因此在我们的子画面上调用drawInContext s表示动画的每一帧。这个函数不需要重绘任何东西,但它可以用来调用委托函数:)

Since our progress property can be animated, drawInContext is called on our sublass for every frame of an animation. This function doesn't need to redraw anything, however it can be used to call a delegate function :)

这里是类接口:

@protocol TAProgressLayerProtocol <NSObject>

- (void)progressUpdatedTo:(CGFloat)progress;

@end

@interface TAProgressLayer : CALayer

@property CGFloat progress;
@property (weak) id<TAProgressLayerProtocol> delegate;

@end

并且执行:

@implementation TAProgressLayer

// We must copy across our custom properties since Core Animation makes a copy
// of the layer that it's animating.

- (id)initWithLayer:(id)layer
{
    self = [super initWithLayer:layer];
    if (self) {
        TAProgressLayer *otherLayer = (TAProgressLayer *)layer;
        self.progress = otherLayer.progress;
        self.delegate = otherLayer.delegate;
    }
    return self;
}

// Override needsDisplayForKey so that we can define progress as being animatable.

+ (BOOL)needsDisplayForKey:(NSString*)key {
    if ([key isEqualToString:@"progress"]) {
        return YES;
    } else {
        return [super needsDisplayForKey:key];
    }
}

// Call our callback

- (void)drawInContext:(CGContextRef)ctx
{
    if (self.delegate)
    {
        [self.delegate progressUpdatedTo:self.progress];
    }
}

@end

我们然后可以将图层添加到我们的主图层:

We can then add the layer to our main layer:

TAProgressLayer *progressLayer = [TAProgressLayer layer];
progressLayer.frame = CGRectMake(0, -1, 1, 1);
progressLayer.delegate = self;
[_sceneView.layer addSublayer:progressLayer];

并将其与其他动画一起制作动画:

And animate it along with the other animations:

CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"progress"];
anim.duration = 4.0;
anim.beginTime = 0;
anim.fromValue = @0;
anim.toValue = @1;
anim.fillMode = kCAFillModeForwards;
anim.removedOnCompletion = NO;

[progressLayer addAnimation:anim forKey:@"progress"];

最后,随着动画的进行,代表将被回叫:

Finally, the delegate will be called back as the animation progresses:

- (void)progressUpdatedTo:(CGFloat)progress
{
    // Do whatever you need to do...
}

这篇关于核心动画进度回调的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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