2015-10-05 13 views
8

Gestisco l'animazione di un CALayer su un UIBezierPath.Come animare solo una percentuale dell'animazione completa CALayer su un UIBezierPath?

Quello che sto cercando di realizzare è di animare solo una percentuale del percorso, ad esempio solo il 25% del percorso, con il livello che rimane in quella posizione (al 25%).

Qual è il modo di fare questo? Ecco il mio codice, anima sempre il percorso completo.

let aPath = UIBizierPath(CGPath: somePath) 
let anim = CAKeyframeAnimation(keyPath: "position") 
anim.path = aPath.CGPath 
anim.rotationMode = kCAAnimationRotateAuto 
anim.repeatCount = 1 
anim.fillMode = kCAFillModeForwards 
anim.removedOnCompletion = false 
anim.duration = 3.0 
anim.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) 

ticker.addAnimation(anim, forKey: "animate_ticker") 

risposta

2

semplice cambiamento di una proprietà:

anim.repeatCount = 0.25  

Ecco un excellent article on animation timing, si può imparare ad avere anche un controllo più fine sulle animazioni.

Aggiungi:
1. Per ottenere ciò che si vuole, il modo più vicino è quello di avere un sottotracciato 25%, ecco alcuni helper method.

2.If che può sopportare la differenza di velocità, utilizzare il metodo di cui sopra, e impostare di nuovo la posizione quando l'animazione si conclude:

ticker.position = ticker.presentationLayer().position 
+1

Il problema con questo è che l'animazione non si fermerà a 1/4 della via attraverso il * percorso *, solo 1/4 del passaggio attraverso l'animazione * *. Pertanto con una funzione di temporizzazione 'kCAMediaTimingFunctionEaseInEaseOut' e 0,25 per' repeatCount', l'animazione si fermerà prima del previsto. Inoltre, la funzione di cronometraggio verrà comunque applicata all'intera durata dell'animazione - e quindi sembrerà accelerare e poi improvvisamente fermarsi, che può o meno essere ciò che l'OP vuole. – Hamish

+0

@ originaluser2, sei corretto. Ho trovato che l'animazione non si fermava perfettamente dove pensavo, quindi questo lo spiega! Grazie! Sto cercando 1/4 del percorso, non l'animazione. –

0

Hai provato a impostare fromValue e toValue proprietà? Dovrebbe funzionare se si imposta fromValue a 0,0 e toValue a 0,25

+1

'fromValue' e' toValue' sono introdotti in 'CABasicAnimation' che non è una superclasse a' CAKeyframeAnimation' –

0

Non solo CGPath è opaco, ma anche CAAnimation non supporta alcuna aggiornamenti o notifiche per le animazioni in corso (ovvero dopo iniziato ma prima finito). Le uniche entità coinvolte sono le animazioni stesse e CALayer -s a cui è applicato.

Quindi, le opzioni sono:

(alcune opzioni possono sembrare troppo spaventoso, ma non lo sono, così ho fatto un progetto di esempio, vedi sotto)

repeatCount

Come wj2061 accennato è his answer voi può modificare l'animazione repeatCount. Contro è che animerà 0,25 del tempo di animazione, non 0,25 di percorso

CAShapeLayer

Se, per caso, si può rappresentare il vostro segmento ticker con CAShapeLayer allora è possibile animare strokeStart e strokeEnd così sarà simile segmento si muove lungo il percorso

Clever repeatCount

È possibile calcolare quali repeatCount valore che l'animazione si ferma a 0,25 del percorso.

  • acchiappare Bezier lib
  • estratto Bezier dalla funzione di temporizzazione con getControlPointAtIndex:
  • risolvere bezier per ottenere il suo "valore di progresso" (di solito chiamato t) per i quali il valore 'y' di bezier abbinerà al tuo "necessaria progresso" 'x' valore (0,25)
  • calcolare di Bezier per quella t - questo è il valore esatto di repeatCount è necessario

Anim CORTEGGIAMENTO con CAAnimation, tutto da solo

sorta di avanzata

  • acchiappare i lib Bezier
  • creare personalizzato sottoclasse CALayer con proprietà dinamica, diciamo proprietà sintetizzati rideProgress
  • aggiuntivi per tracciato Bezier (da Bezier lib, non CGPath) e sottolivello (per esempio, rideLayer) per animare
  • override needsDisplayForKey: per rideProgress chiave e initWithLayer: per tutte le proprietà introdotte MA utilizzare self.rideLayer?.presentationLayer() invece di copiare rideLayer
  • ignorare uno di questi: drawInContext: e disegnare ciò che è necessario in esso; o (migliore) display, in display recuperare il valore corrente rideProgress da presentationLayer e aggiornare il sottolivello, quindi chiamare super. In entrambi i casi, utilizzare bezier lib per calcolare la posizione e la rotazione per sottolivello di conseguenza per valore attuale rideProgress
  • non dimenticate di CATransaction.setDisableActions(true) prima di impostare qualsiasi proprietà animatable di qualsiasi livello
  • infine, utilizzare qualsiasi tipo di CAAnimation o di animazione implicito rideProgress proprietà

percorso Split

Anche in questo caso, suggerito da wj2061. È possibile dividere il percorso in modo una delle due metà rappresenterà 0,25 dell'originale


Here è esempio di implementazione di tutto ciò di cui sopra tranne "percorso Split". Non ho eseguito test sul campo su questo codice, è solo un concetto funzionante. XCode 7.3.1, Swift.


Materiali utilizzati: Wiki on Cubic function, Great article about operations on beziers, Cubic equations solving method line-by-line

0

stavo correndo lo stesso problema, e ho voluto animare il disegno di un percorso, ma solo una percentuale di esso.

Quello che ho finito per fare era impostare strokeStart e strokeEnd del livello con gli stessi valori in virgola mobile dell'animazione.

Quindi, nel tuo esempio, prova a impostare anim.fromValue = 0.0f, anim.toValue = 0.6f e anche ticker.strokeStart=0.0f e ticker.strokeEnd = 0.6f.

Questo ha disegnato con successo solo il 60% del percorso e lo ha anche animato!

+0

Non ricordo i motivi esatti, ma questo non ha funzionato. (Non sono quello che ha downvoted) –

Problemi correlati