0

在为关键帧设置动画时,我似乎遗漏了明显的东西。我查看了许多代码示例,包括文档MoveMe中引用的 Apple's ,CAKeyframeAnimation但是,我找不到会导致我所看到的差异。

我创建 a CGMutablePathRef,然后创建 aCAKeyframeAnimation并将其设置为沿路径为图像视图设置动画。创建了一个动画组,因此我可以在完成后删除视图。

然而,我的动画从未出现。直到我旋转设备。似乎重新布局视图会导致动画启动。我尝试了明显的 like[theImageView setNeedsDisplay]或 even setNeedsLayout,以及容器视图。然而,当我需要时,仍然无法让它工作。它们仅在我旋转设备时出现。

在下文中,-cgPathFromArray:采用 anNSArray内部操作码转换为CGPathRef. 它被验证是正确的,因为当我旋转设备时,动画确实会沿着编程的路径显示。

- (void) animateImage: (NSString*) imageName
               onPath: (NSArray*) path
         withDuration: (NSString*) duration
{
    if (self.sceneView)
    {
        CGMutablePathRef    animationPath   =   [self cgPathFromArray: path];

        if (animationPath)
        {
            UIImage*    image       =   [self findImage: imageName];

            if (image)
            {
                UIImageView*    imageView   =   [[UIImageView alloc] initWithFrame: CGRectMake(0, 0, image.size.width, image.size.height)];

                if (imageView)
                {
                    CAKeyframeAnimation*    keyFrameAnimation   =   [CAKeyframeAnimation animationWithKeyPath: @"position"];

                    imageView.image = image;

                    [self.sceneView addSubview: imageView];

                    keyFrameAnimation.removedOnCompletion   =   YES;
                    keyFrameAnimation.fillMode              =   kCAFillModeForwards;
                    keyFrameAnimation.duration              =   duration.floatValue;
                    keyFrameAnimation.timingFunction        =   [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionLinear];
                    keyFrameAnimation.repeatCount = 0;

                    keyFrameAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];

                    [keyFrameAnimation setPath: animationPath];

                    //group animation with termination block to cleanup
                    CAAnimationGroup* group     =   [CAAnimationGroup animation];

                    group.duration              =   keyFrameAnimation.duration;
                    group.removedOnCompletion   =   YES;
                    group.fillMode              =   kCAFillModeForwards;
                    group.animations            =   @[keyFrameAnimation];

                    CorpsAnimationCompletionBlock theBlock = ^void(void)
                    {
                        [imageView removeFromSuperview];
                    };

                    [group setValue: theBlock
                             forKey: kCorpsAnimationCompletionBlock];

                    group.delegate = self;

                    [imageView.layer addAnimation: group
                                           forKey:  nil];
                }
            }
        }
    }
}

任何人都可以帮助解决这个问题吗?

4

1 回答 1

1

您可能遇到了麻烦,因为您在将图层添加到可见图层树的同一事务中将动画添加到图层。Core Animation 不喜欢将动画附加到尚未提交的图层上。您可以[CATransaction flush]在添加图层后解决此问题。

由于过度嵌套,您的代码很难看。考虑使用提前返回使其更具可读性。

-[UIImage initWithImage:]此外,您正在显式创建初始化程序将为您创建的同一帧。

如果您使用动画组并简单地设置代理以便在动画结束时执行块,则有一种更简单的方法。您可以开始一个CATransaction,设置事务的完成块,然后添加动画,然后提交事务。

因此:

- (void) animateImage:(NSString *)imageName onPath: (NSArray *)path
    withDuration: (NSString *)duration
{
    if (!self.sceneView)
        return;

    CGMutablePathRef animationPath = [self cgPathFromArray:path];
    if (!animationPath)
        return;

    UIImage *image = [self findImage:imageName];
    if (!image)
        return;

    UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
    [self.sceneView addSubview: imageView];

    // commit the implicit transaction so we can add an animation to imageView.
    [CATransaction flush];

    [CATransaction begin]; {
        [CATransaction setCompletionBlock:^{
            [imageView removeFromSuperview];
        }];

        CAKeyframeAnimation *animation = [CAKeyframeAnimation
            animationWithKeyPath:@"position"];
        animation.duration = duration.floatValue;
        animation.timingFunction = [CAMediaTimingFunction
            functionWithName:kCAMediaTimingFunctionLinear];
        animation.path = animationPath;
        [imageView.layer addAnimation:animation forKey:animation.keyPath];
    } [CATransaction commit];
}
于 2013-02-27T22:31:17.607 回答