Базовая анимация "флип" анимация - PullRequest
3 голосов
/ 28 мая 2010

Я хочу использовать Core Animation для симуляции анимации флип-часов в приложении Mac. В настоящее время у меня есть три CALayer, представляющих верхнюю и нижнюю половину цифры, и третий, используемый для представления анимации при переворачивании (решение найдено в следующей статье: Создание флип-часов для iPad с 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 Ответ

1 голос
/ 21 сентября 2010

* После 1001 *

anim.removedOnCompletion = NO; 

попробуйте вставить этот код:

anim.fillMode = kCAFillModeForwards;

И дай мне знать. По сути, фрагмент кода должен предотвращать «сброс», который вызывает мерцание.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...