核心动画'翻转'动画

时间:2010-05-28 12:05:03

标签: cocoa core-animation

我希望使用Core Animation在Mac应用程序中模拟翻转时钟动画。目前我有三个CALayer代表数字的上半部分和下半部分,第三个用于表示翻转动画(在以下文章中找到解决方案:Creating an iPad flip-clock with Core Animation

翻转层的动画分为两个阶段:从数字的顶部到中间翻转,然后从中间翻到底部。为了实现这一点,我使用了一个委托函数,只要动画结束就会调用它:

- (void)animationDidStop:(CAAnimation *)oldAnimation finished:(BOOL)flag
{
    int digitIndex = [[oldAnimation valueForKey:@"digit"] intValue];    
    int currentValue = [[oldAnimation valueForKey:@"value"] intValue];

    NSMutableArray *digit = [digits objectAtIndex:digitIndex];
    CALayer *flipLayer = [digit objectAtIndex:tickerFlip];
    CALayer *bottomLayer = [digit objectAtIndex:tickerBottom];

    if([[oldAnimation valueForKey:@"state"] isEqual:@"top"] && flag) {
        NSLog(@"Top animation finished");

        [CATransaction begin];
        [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
        flipLayer.contents = [bottomImages objectAtIndex:currentValue];
        flipLayer.anchorPoint = CGPointMake(0.0, 1.0);
        flipLayer.hidden = NO;
        [CATransaction commit];

        CABasicAnimation *anim = [self generateAnimationForState:@"bottom"];
        [anim setValue:[NSString stringWithFormat:@"%d", digitIndex] forKey:@"digit"];
        [anim setValue:[NSString stringWithFormat:@"%d", currentValue] forKey:@"value"];
        [flipLayer addAnimation:anim forKey:nil];
    } else if([[oldAnimation valueForKey:@"state"] isEqual:@"bottom"] && flag) {
        NSLog(@"Bottom animation finished");

        // Hide our flip layer
        [CATransaction begin];
        [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
        bottomLayer.contents = [bottomImages objectAtIndex:currentValue];
        flipLayer.hidden = YES;
        flipLayer.anchorPoint = CGPointMake(0.0, 0.0);
        [CATransaction commit];
    }
}

此委托函数使用辅助函数,该函数根据其状态生成翻转图层的变换:

- (CABasicAnimation *)generateAnimationForState:(NSString *)state
{
    CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform"];
    anim.duration = 0.15;
    anim.repeatCount = 1;

    // Check which animation we're doing
    if([state isEqualToString:@"top"]) 
    {
        anim.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(0.0f, 1, 0, 0)];
        anim.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI/2, 1, 0, 0)];
    } 
    else 
    {
        anim.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(-M_PI/2, 1, 0, 0)];
        anim.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(0.0f, 1, 0, 0)];
    }

    anim.delegate = self;
    anim.removedOnCompletion = NO;

    // Set our animations state
    [anim setValue:state forKey:@"state"];

    return anim;
}

此解决方案有效但在动画进行过程中会导致轻微闪烁。我相信这是由于我的翻转层在'顶部'和'底部'动画之间重置的转换。重要的是要注意,在动画的第一阶段完成后,我将翻转层锚点设置到图像的顶部,确保翻转正确旋转。

目前我不确定我的动画是否已经设置得最佳。我一般都是转换和核心动画的新手。有人能指出我正确的方向吗?

1 个答案:

答案 0 :(得分:1)

anim.removedOnCompletion = NO; 

尝试插入此代码:

anim.fillMode = kCAFillModeForwards;

让我知道。本质上,代码片段可以防止导致闪烁的“重置”。