2013-08-22 3 views
26

Ich habe einen CAShapeLayer, der einen CGPath enthält. Mit der integrierten Animation von iOS kann ich diesen Pfad mithilfe einer Animation leicht in einen anderen mappen:Tweening/Interpolation zwischen zwei CGPaths/UIBeziers

CABasicAnimation *morph = [CABasicAnimation animationWithKeyPath:@"path"]; 
    morph.fromValue = (id)myLayer.path; 
    mayLayer.path = [self getNewPath]; 
    morph.toValue = (id)myLayer.path; 
    morph.duration = 0.3; 
    [myLayer addAnimation:morph forKey:nil]; 

Das funktioniert perfekt.

Allerdings würde ich jetzt gerne während einer Ziehoperation schrittweise zwischen diesen Pfaden morphen. Um dies zu tun, muss ich den interpolierten Pfad an jedem Punkt während des Ziehens abrufen können. Gibt es eine Möglichkeit, iOS dafür zu fragen?

+0

In nicht-triviale Fällen wird die eingebaute Morphing von Pfaden ziemlich schnell unbrauchbar. Siehe das Problem und die hier beschriebenen Erklärungen: http://stackoverflow.com/a/17864445/438982 – ipmcc

+0

Das stimmt, aber in meinem Fall sieht das Morphing gut aus ... – tarmes

Antwort

77

Dies ist eigentlich viel einfacher als Sie zuerst denken würden und verwendet Animationen mit "Nein" Geschwindigkeit (pausiert). Jetzt können Sie mit der pausierten Animation, die der Ebene hinzugefügt wurde, den Zeitversatz ändern, um zu einer bestimmten Zeit innerhalb der Animation zu springen.

Wenn Sie nicht vorhaben, die Animation selbst auszuführen (dh, sie nur manuell zu steuern), würde ich vorschlagen, die Dauer der Animation auf 1 zu ändern. Dies bedeutet, dass Sie den Zeitversatz von 0 auf 1 ändern von 0% bis 100%. Wenn Ihre Dauer 0,3 war (wie in Ihrem Beispiel), würden Sie den Zeitversatz stattdessen auf einen Wert zwischen 0 und 0,3 setzen.

Implementierung

Wie ich oben gesagt, gibt es sehr wenig Code in diesem kleinen Trick beteiligt ist.

  1. (Optional) Stellen Sie die Dauer auf 1,0
  2. Stellen Sie die speed der Schicht (ja, sie entsprechen CAMediaTiming) oder die Animation auf 0,0
  3. Während der Ziehbewegung oder Schieberegler (wie in meinem Beispiel) Setzen Sie die der Ebene oder Animation (je nachdem, was Sie in Schritt 2 getan haben).

Dies ist, wie ich meine Animation + Formebene konfiguriert

CABasicAnimation *morph = [CABasicAnimation animationWithKeyPath:@"path"]; 
morph.duration = 1.; // Step 1 
morph.fromValue = (__bridge id)fromPath; 
morph.toValue = (__bridge id)toPath; 
[self.shapeLayer addAnimation:morph forKey:@"morph shape back and forth"]; 

self.shapeLayer.speed = 0.0; // Step 2 

und der Schieber Aktion:

- (IBAction)sliderChanged:(UISlider *)sender { 
    self.shapeLayer.timeOffset = sender.value; // Step 3 
} 

Sie können unter das Endergebnis sehen. Glückliche Kodierung!

enter image description here

+0

Fantastisch, danke. Ich hatte keine Ahnung von der Existenz des timeOffset. Was würden Sie tun, wenn Sie die Animation selbst verwenden möchten? – tarmes

+0

@Tarmes Das hängt von den Besonderheiten der Interaktion ab. Sie können die Animation noch pausieren und den Zeitversatz ändern (in diesem Fall von 0 auf 0.3). Sie können die Animation fortsetzen, indem Sie die Geschwindigkeit erneut auf 1 setzen. Wenn die Animation ausgeführt wird, wenn Sie mit ihr interagieren möchten, können Sie den aktuellen Wert mit '[layer convertTime: CACurrentMediaTime() fromLayer: nil]' ermitteln. Weitere Informationen finden Sie [diese Antwort] (http://stackoverflow.com/a/3003922/608157). –

+6

Diese großartige Technik hat mich dazu inspiriert, einen Button mit einem ► (Wiedergabe) - oder ❚❚ (Pause) -Symbol zu erstellen, das sich gut zwischen den beiden ändert. Sehen Sie es in Aktion: http://instagram.com/p/l6a8uDHDk7 Und hier ist die Quelle: http://gist.github.com/raphaelschaad/9734463 –