2012-03-02 30 views
13

Użyłem CAKeyframeAnimations do animowania właściwości warstwy transform.rotation i transform.translation.x, ale mam problem z nieuprawnionym animowaniem właściwości transform. Mam warstwę, która musi animować się między dwoma stanami, a domyślna interpolacja CABasicAnimation jest całkowicie niepoprawna i nie podąża ścieżką, którą chcę. CAKeyframeAnimacja na ratunek, a przynajmniej tak myślałem. Każda próba animacji transform przy użyciu CAKeyframeAnimation powoduje natychmiastowe przyciąganie widoku do ostatecznej transformacji, podczas gdy inne animacje działają. Jeśli usuniemy pierwszą połowę poniższej funkcji i pozwolę, aby moje zdarzenia "przekształcenia" używały CABasicAnimation na dole, animacja jest w porządku - ale z niepoprawnie interpolowanymi transformacjami po drodze.Jak animować CATransform3D za pomocą CAKeyframeAnimation?

Moja warstwa delegat wdrożył następujące:

- (id <CAAction>) actionForLayer:(CALayer *)layer forKey:(NSString *)event 
{  
    if ([event isEqualToString:@"transform"]) 
    { 
     CGSize startSize = ((CALayer *)self.layer.presentationLayer).bounds.size; 
     CGSize endSize = self.layer.bounds.size; 

     CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:event]; 
     animation.duration = 0.25; 

     NSMutableArray *values = [NSMutableArray array]; 

     int stepCount = 10; 
     for (int i = 0; i < stepCount; i++) 
     { 
      CGFloat p = i/(float)(stepCount - 1); 
      CGSize size = [self interpolateBetweenSize:startSize andSize:endSize percentage:p]; 
      CATransform3D transform = [self transformForSize:size]; 
      [values addObject:[NSValue valueWithCATransform3D:transform]]; 
     } 

     animation.values = values; 
     return animation; 
    } 

    // All other animations use this basic animation 
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:event]; 
    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; 
    animation.removedOnCompletion = YES; 
    animation.fillMode = kCAFillModeForwards; 
    animation.duration = 0.25; 
    return animation; 
} 

Moja przekształcić to tłumaczenie następnie obracać, ale myślę, że animacja grupa z osobne animacje klatek kluczowych animacji poprzez tłumaczenie i A Obrót spowodowałoby szalony miasto. Potwierdziłem, że rozmiar transformacji & jest poprawny dla wszystkich wartości p, które przechodzę, a p ściśle mieści się w zakresie od 0 do 1.

Próbowałem ustawić inną niż domyślną funkcję taktowania, próbowałem ustawienia szereg funkcji czasowych, pominąłem keyTImes, ustawiłem repeatCount na 0, removedOnCompletion = YES i fillMode of forward i bez efektu. Czy nie tworzę poprawnie animacji klatek kluczowych transformacji?

+1

Czy mógłbyś wyjaśnić dokładny efekt, który próbujesz osiągnąć? Opisujesz to jako tłumaczenie, po którym następuje rotacja, ale z twojego kodu wygląda na to, że granice są również animowane - czy to prawda?Chcesz, aby warstwa się przesuwała, a następnie obracała, z granicami rosnącymi lub zmniejszającymi się w sposób ciągły w obu fazach animacji ruchu/obracania? – GSnyder

+0

Dlaczego musi być ukryty? Ten kod wygląda na zhakowany. Jeśli chcesz mieć precyzyjną kontrolę, po prostu nie twórz animacji i nie dodawaj jej bezpośrednio do warstwy, o której mówisz, że już działasz? Zwróć także 'nil' z tej metody delegatów, jeśli chcesz, aby rzeczy używały domyślnej animacji. –

Odpowiedz

0

Ta technika działa z powrotem w systemie iOS 3, ale wydawała się być uszkodzona w systemie iOS 5.0.

5.1 'magicznie' naprawiono to, wydawało się, że jest to błąd w iOS 5.0. Zrobiłbym radar, ale teraz działa on w wersji 5.1.

@Gsnyder: Niektóre tła: Eksperymentuję z Clear-like UI (dla czegoś zupełnie niezwiązanego z Clear) i wymyśliłem: http://blog.massivehealth.com/post/18563684407/clear. To powinno tłumaczyć potrzebę tłumaczenia na język obrót o numer &.

Stworzyłem przejście migawki, które dzieli widok na N warstw (zamiast tylko 2), które wyglądają tak, gdy są oglądane z boku: /////.

Mój kod nie animuje granic, używa rozmiaru w każdym kroku, aby określić niezbędną transformację.

@ Paul.s: Implicit pozwala mi zachować tę abstrakcję w samej klasie warstw bez zanieczyszczania kontrolera widoku, który jest jego właścicielem. Kontroler widoku powinien po prostu zmieniać granice, a warstwa powinna się odpowiednio poruszać. Nie jestem fanem kontrolerów widoku mających dziesiątki niestandardowych animacji, gdy same widoki mogą sobie z tym poradzić.

Potrzebuję użyć animacji klatki kluczowej, ponieważ domyślna animacja między transformacjami warstw/i _ animuje przez niepoprawne kąty, więc /// \ warstwy nie ustawiają się w linii w trakcie transformacji. Animacje klatki kluczowej zapewniają prawidłowe wyrównanie krawędzi podczas ich animacji.

Rozważam zamknięcie tego, wydaje się, że jest to błąd w iOS 5.0 i od tego czasu został naprawiony. Dziękuję wszystkim.

0
(void)animateViewWith3DCurrentView:(UIView *)currentView withPoing:(CGPoint)movePoint 
{ 
    //flip the view by 180 degrees in its place first. 
    currentView.layer.transform =   CATransform3DRotate(currentView.layer.transform,myRotationAngle(180), 0, 1, 0); 

    //set the anchor point so that the view rotates on one of its sides. 
    currentView.layer.anchorPoint = CGPointMake(0.5, 0.5); 

    //Set up scaling 

    CABasicAnimation *resizeAnimation = [CABasicAnimation animationWithKeyPath:kResizeKey]; 

    //we are going to fill the screen here. So 423,337 
    [resizeAnimation setToValue:[NSValue valueWithCGSize:CGSizeMake(423, 337)]]; 
    resizeAnimation.fillMode   = kCAFillModeForwards; 
    resizeAnimation.removedOnCompletion = NO; 

    // Set up path movement 

    UIBezierPath *movePath = [UIBezierPath bezierPath]; 

    //the control point is now set to centre of the filled screen. Change this to make the path different. 
    // CGPoint ctlPoint  = CGPointMake(0.0, 0.5); 
    CGPoint ctlPoint  = CGPointMake(1024/2, 768/2); 

    //This is the starting point of the animation. This should ideally be a function of the frame of the view to be animated. Hardcoded here. 

    // Set here to get the accurate point.. 
    [movePath moveToPoint:movePoint]; 

    //The anchor point is going to end up here at the end of the animation. 
    [movePath addQuadCurveToPoint:CGPointMake(1024/2, 768/2) controlPoint:ctlPoint]; 

    CAKeyframeAnimation *moveAnim = [CAKeyframeAnimation animationWithKeyPath:kPathMovement]; 

    moveAnim.path    = movePath.CGPath; 
    moveAnim.removedOnCompletion = YES; 

    // Setup rotation animation 

    CABasicAnimation* rotateAnimation = [CABasicAnimation animationWithKeyPath:kRotation]; 
    //start from 180 degrees (done in 1st line) 
    CATransform3D fromTransform  = CATransform3DMakeRotation(myRotationAngle(180), 0, 1, 0); 
    //come back to 0 degrees 
    CATransform3D toTransform   = CATransform3DMakeRotation(myRotationAngle(0), 0, 1, 0); 

    //This is done to get some perspective. 
    CATransform3D persp1 = CATransform3DIdentity; 
    persp1.m34 = 1.0/-3000; 

    fromTransform = CATransform3DConcat(fromTransform, persp1); 
    toTransform = CATransform3DConcat(toTransform,persp1); 

    rotateAnimation.toValue    = [NSValue valueWithCATransform3D:toTransform]; 
    rotateAnimation.fromValue   = [NSValue valueWithCATransform3D:fromTransform]; 
    //rotateAnimation.duration   = 2; 
    rotateAnimation.fillMode   = kCAFillModeForwards; 
    rotateAnimation.removedOnCompletion = NO; 


    // Setup and add all animations to the group 

    CAAnimationGroup *group = [CAAnimationGroup animation]; 

    [group setAnimations:[NSArray arrayWithObjects:moveAnim,rotateAnimation, resizeAnimation, nil]]; 

    group.fillMode   = kCAFillModeForwards; 
    group.removedOnCompletion = NO; 
    group.duration   = 0.7f; 
    group.delegate   = self; 

    [group setValue:currentView forKey:kGroupAnimation]; 

    [currentView.layer addAnimation:group forKey:kLayerAnimation]; 
} 
Powiązane problemy