2013-07-20 12 views
9

Ich versuche, eine Sequenz von Animationen zu machen, ich habe in CAAnimationGroup die richtige Klasse gefunden, um dieses Objekt zu erreichen. In der Praxis füge ich verschiedene Subviews hinzu und möchte ihren Eintrag mit einem Bounce-Effekt animieren. Tatsache ist, dass ich sehen möchte, dass ihre Animationen direkt nach dem letzten geschehen. Ich weiß, dass ich den Delegierten einstellen kann, aber ich dachte, dass die CAAnimationGroup die richtige Wahl war.
Später entdeckte ich, dass die Gruppenanimation nur zu einer Ebene gehören kann, aber ich brauche es auf verschiedenen Ebenen auf dem Bildschirm. Natürlich auf der Hosting-Ebene funktioniert nicht. Einige Vorschläge?Sequenzanimation mit CAAnimationGroup

- (void) didMoveToSuperview { 
    [super didMoveToSuperview]; 
    float startTime = 0; 
    NSMutableArray * animArray = @[].mutableCopy; 
    for (int i = 1; i<=_score; i++) { 
     NSData *archivedData = [NSKeyedArchiver archivedDataWithRootObject: self.greenLeaf]; 
     UIImageView * greenLeafImageView = [NSKeyedUnarchiver unarchiveObjectWithData: archivedData]; 
     greenLeafImageView.image = [UIImage imageNamed:@"greenLeaf"]; 
     CGPoint leafCenter = calculatePointCoordinateWithRadiusAndRotation(63, -(M_PI/11 * i) - M_PI_2); 
     greenLeafImageView.center = CGPointApplyAffineTransform(leafCenter, CGAffineTransformMakeTranslation(self.bounds.size.width/2, self.bounds.size.height)); 
     [self addSubview:greenLeafImageView]; 

     //Animation creation 
     CAKeyframeAnimation *bounceAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"]; 
     greenLeafImageView.layer.transform = CATransform3DIdentity; 
     bounceAnimation.values = @[ 
            [NSNumber numberWithFloat:0.5], 
            [NSNumber numberWithFloat:1.1], 
            [NSNumber numberWithFloat:0.8], 
            [NSNumber numberWithFloat:1.0] 
            ]; 

     bounceAnimation.duration = 2; 
     bounceAnimation.beginTime = startTime; 
     startTime += bounceAnimation.duration; 

     [animArray addObject:bounceAnimation]; 
     //[greenLeafImageView.layer addAnimation:bounceAnimation forKey:nil]; 


    } 
    // Rotation animation 
    [UIView animateWithDuration:1 animations:^{ 
     self.arrow.transform = CGAffineTransformMakeRotation(M_PI/11 * _score); 
    }]; 
    CAAnimationGroup * group = [CAAnimationGroup animation]; 
    group.animations = animArray; 
    group.duration = [[ animArray valueForKeyPath:@"@sum.duration"] floatValue]; 
    [self.layer addAnimation:group forKey:nil]; 
} 

Antwort

22

CAAnimationGroup für mehrere mit gemeint CAAnimation Subklassen zusammen gestapelt sind, um eine Animation zu erzeugen, zum Beispiel eine Animation kann eine Skala durchzuführen, wobei die anderen bewegt er sich um, während eine dritte es drehen kann, ist es nicht dazu gedacht, für Verwalten mehrerer Ebenen, aber mehrere überlagerte Animationen.

Das heißt, ich die einfachste Art und Weise denken, Ihr Problem zu lösen, ist es, jede CAAnimation ein beginTime entspricht der Summe der Dauer aller vorherigen zuweisen, zu veranschaulichen:

for i in 0 ..< 20 
{ 
    let view : UIView = // Obtain/create the view...; 
    let bounce = CAKeyframeAnimation(keyPath: "transform.scale") 

    bounce.duration = 0.5; 
    bounce.beginTime = CACurrentMediaTime() + bounce.duration * CFTimeInterval(i); 

    // ... 

    view.layer.addAnimation(bounce, forKey:"anim.bounce") 
} 

Beachten Sie, dass jeder bekommt duration * i, und die CACurrentMediaTime() ist eine Notwendigkeit, wenn Sie die Eigenschaft beginTime verwenden (es ist im Grunde ein hochpräziser Zeitstempel für "jetzt", in Animationen verwendet).Die gesamte Zeile könnte als now + duration * i interpretiert werden.

muss darauf hingewiesen werden, dass, wenn ein CAAnimation s zu einem CAAnimationGroup hinzugefügt wird, dann sein beginTime relative wird beginnen zu der Gruppe Zeit, so dass ein Wert von 5.0 auf einer Animation, würde 5.0 Sekunden, nachdem die ganze Gruppe beginnt sein. In diesem Fall verwenden Sie nicht die CACurrentMediaTime()

+0

Großartig, Danke! – Andrea

2

Wenn Sie the documentation überprüfen, werden Sie feststellen, dass CAAnimationGroup erbt von CAAnimation, und dass CAAnimation kann nur einem CALayer zugeordnet werden. Es ist wirklich Absicht, es einfach zu machen, mehrere Animationen zu erstellen und zu verwalten, die Sie gleichzeitig auf CALayer anwenden möchten, nicht auf Manager-Animationen für mehrere CALayer Objekte.

Um die Sequenzierung von verschiedenen Animationen zwischen verschiedenen CALayer oder UIView Objekte zu behandeln, eine Technik, die ich benutze ist ein NSOperation für jedes Objekt/Animation zu erstellen, so dass sie dann werfen in eine NSOperationQueue die Sequenzierung zu verwalten. Dies ist ein wenig kompliziert, da Sie den Callback der Animationsvervollständigung verwenden müssen, um dem NSOperation zu erzählen, dass es beendet ist, aber wenn Sie eine gute Animationsmanagementunterklasse von NSOperation schreiben, kann es ziemlich bequem sein und Ihnen ermöglichen, anspruchsvolle Sequenzierungswege zu erstellen. Der günstigste Weg, um das Sequenzierungsziel zu erreichen, besteht darin, einfach die beginTime-Eigenschaft auf Ihr CAAnimation-Objekt (das aus der Übernahme des Protokolls CAMediaTiming stammt) zu setzen, um das gewünschte Timing zu erhalten.

Mit diesem gesagt, werde ich Sie auf einen Code, den ich geschrieben und Open-Source, um genau den gleichen Anwendungsfall, den Sie beschreiben, zu lösen. Sie können es finden on github here (gleicher Code enthalten). Ich werde die folgenden Hinweise hinzufügen:

  • Mein Animation-Management-Code lassen Sie Ihre Animation in einer plist definieren, indem die Reihenfolge und den Zeitpunkt der Bildänderungen zu identifizieren, Maßstabsänderungen, Positionsänderungen usw. Es ist eigentlich ziemlich bequem und saubere um deine Animation in einer Plist-Datei anstatt in Code anzupassen (weshalb ich das geschrieben habe).
  • Wenn erwartet wird, dass der Benutzer nicht mit den von Ihnen erstellten Teilansichten interagiert, ist es tatsächlich viel besser (weniger Aufwand), Ebenenobjekte zu erstellen, die als Unterebenen zur Ebene der Hosting-Ansicht hinzugefügt werden.
+0

Ich werde in, dass es scheint ein wirklich interessanter Ansatz – Andrea