2013-08-22 5 views
26

Ho un CAShapeLayer che contiene un CGPath. Utilizzando l'animazione built-in di iOS posso facilmente morph questo percorso in un altro utilizzando un'animazione:Interpolazione/interpolazione tra due 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]; 

che funziona perfettamente.

Tuttavia, mi piacerebbe ora trasformarsi gradualmente tra questi percorsi durante un'operazione di trascinamento. Per fare questo ho bisogno di essere in grado di recuperare il percorso interpolato in qualsiasi punto durante il trascinamento. C'è un modo per chiedere a iOS questo?

+0

Nei casi non banali, costruito in morphing di percorsi diventa inutile abbastanza rapidamente. Vedi il problema e le spiegazioni qui descritti: http://stackoverflow.com/a/17864445/438982 – ipmcc

+0

È vero, ma nel mio caso il morphing sembra buono ... – tarmes

risposta

77

Questo è in realtà molto più semplice di quanto si pensi inizialmente e utilizza animazioni con velocità "no" (in pausa). Ora con l'animazione in pausa aggiunta al livello è possibile modificare l'offset temporale per passare a un momento specifico all'interno dell'animazione.

Se non si sta pianificando l'esecuzione dell'animazione da solo (vale a dire solo controllarlo manualmente), suggerirei di modificare la durata dell'animazione su 1. Ciò significa che si modifica l'offset di tempo da 0 a 1 durante lo spostamento da 0% a 100%. Se la tua durata era 0.3 (come nel tuo esempio), allora dovresti impostare l'offset del tempo su un valore compreso tra 0 e 0.3.

Attuazione

come ho detto sopra, c'è ben poco codice coinvolta in questo piccolo trucco.

  1. (opzionale) Impostare la durata di 1,0
  2. Impostare la speed dello strato (sì sono conformi alle CAMediaTiming) oppure l'animazione per 0,0
  3. Durante il movimento di trascinamento o il cursore (come nel mio esempio) imposta il timeOffset del livello o dell'animazione (a seconda di cosa hai fatto nel passaggio 2).

Ecco come ho configurato il mio animazione + forma strato

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 

E l'azione di scorrimento:

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

Potete vedere il risultato finale di seguito. Buona programmazione!

enter image description here

+0

Fantastico, grazie. Non avevo idea dell'esistenza di timeOffset. Cosa faresti se avessi intenzione di utilizzare l'animazione da solo? – tarmes

+0

@tarmes Che dipende dalle specifiche dell'interazione. È ancora possibile mettere in pausa l'animazione e modificare l'offset di tempo (in questo caso da 0 a 0,3). È possibile riprendere l'animazione riportando nuovamente la velocità su 1. Se l'animazione è in esecuzione quando vuoi interagire con essa, puoi ottenere il valore corrente usando '[layer convertTime: CACurrentMediaTime() fromLayer: nil]'. Vedere [questa risposta] (http://stackoverflow.com/a/3003922/608157) per ulteriori informazioni. –

+6

Questa grande tecnica mi ha ispirato a fare un pulsante con un'icona ► (riproduzione) o ❚❚ (pausa) che si trasforma in modo graduale tra i due. Guardalo in azione: http://instagram.com/p/l6a8uDHDk7 Ed ecco la fonte: http://gist.github.com/raphaelschaad/9734463 –