2010-07-14 12 views
5

Questo è stato alla guida mi noci ...Forza il senso di rotazione del CALayer?

Considerando "piano" è una CALayer, ruoto che nell'asse X:

plane.transform = CATransform3DMakeRotation(180 * M_PI/180.0f, 1.0f, 0.0f, 0.0f); 

e questo lo rende ruotare in senso orario, che è perfetto.

Ora, ad un certo punto nel tempo, lo voglio per tornare a 0 gradi, per cui uso:

plane.transform = CATransform3DMakeRotation(0 * M_PI/180.0f, 1.0f, 0.0f, 0.0f); 

Il fatto è che ... lo fa in senso antiorario, il che non è quello che voglio :(

Sto supponendo che usi il percorso di rotazione più breve, ma anche se gli dico di andare a 360 gradi invece, quando è finito e gli dico di riavviare l'animazione, inizia da 360 per andare a 180, e va indietro invece della giusta direzione:

C'è un modo per aggirare questo?

Cosa farei in Actionscript sarebbe:

if (plane.rotationX == 360) plane.rotationX = 0; 

e sarebbe riprendere bene, ma se lo faccio usando CATransform3DMakeRotation entrambe le trasformazioni si scontrano, a causa del l'animazione (penso) e si incasina.

Qualsiasi aiuto sarebbe molto apprezzato!

Grazie

+0

vedo questo è un toughie :( – Andre

risposta

8

Questa domanda si presentava quando stavo cercando di risolvere un problema simile. Volevo ruotare un'immagine di 180 gradi e poi volevo continuare ad andare in giro per una capriola completa. iOS voleva riprendere il percorso più breve. La risposta qui non mi ha aiutato troppo. Ho finito per cercare alcune cose sulle animazioni keyPath e questo ha risolto il mio problema. Di seguito è riportato un esempio dell'approccio.

Per il problema specifico sollevato nella domanda, sono necessari due diversi set di valori KeyFrame, uno per la rotazione iniziale e un altro per il secondo. Ma inserendo un valore intermedio puoi ottenere l'effetto desiderato, cioè prendere il percorso più lungo o forzare la scelta di percorsi ugualmente lunghi, se è quello che vuoi. Ho lasciato alcuni codici di varianti nei commenti, in quanto potrebbero aiutare le persone non familiari con CAKeyFrameAnimation a seguire il codice/comprendere l'intervallo di opzioni.

- (void) somersault; 
{ 

    CALayer* layer = [self layer]; 
    NSMutableArray* keyFrameValues = [NSMutableArray array]; 
    [keyFrameValues addObject:[NSNumber numberWithFloat:0.0]]; 
    //[values addObject:[NSNumber numberWithFloat:M_PI*0.5]]; 
    [keyFrameValues addObject:[NSNumber numberWithFloat:M_PI]]; 
    [keyFrameValues addObject:[NSNumber numberWithFloat:M_PI*1.5]]; 
    [keyFrameValues addObject:[NSNumber numberWithFloat:M_PI*2.0]]; 

    CAKeyframeAnimation* animation = [CAKeyframeAnimation animationWithKeyPath:@"transform"]; 
    [animation setValues:keyFrameValues]; 
    [animation setValueFunction:[CAValueFunction functionWithName: kCAValueFunctionRotateX]];// kCAValueFunctionRotateZ]]; 

    [animation setDuration:0.9]; 
    //[animation setTimingFunction: [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]]; 

    [layer addAnimation:animation forKey:nil]; 

    return; 
} 
+1

Se si desidera un'animazione costante, è possibile impostare 'animation.calculationMode = kCAAnimationPaced' e CoreAnimation interpola gli angoli in modo uniforme nel tempo. – kevboh

1

Credo che il problema è giù per in attesa di un po 'troppo del sistema di animazione implicita, che è fondamentalmente solo andare a interpolare i valori di proprietà di livello da A a B. Questo è grande per una vasta gamma dei casi, ma non ti permette di fare cose come "catena" cambia insieme in sequenza. Ci sono modi per fare quest'ultimo, anche se sono decisamente meno convenienti di quello che stai facendo al momento. Tuttavia, potresti voler indagare su chi fa le cose "correttamente". (Inizia con un altro sguardo al Core Animation Guide.)

Tuttavia, se siete disposti a mettere in su con una soluzione di formaggio, si potrebbe essere in grado di ottenere questo a guardare come si desidera semplicemente continuando a cambiare la rotazione angolo nella stessa direzione ogni volta, piuttosto che a impostarlo su una costante 0 o 180:

// you need to keep track of this somewhere in your code 
// (I've made it static for simplicity, you should do something more sensible) 
static long currentAngle = 0; 

// rotate (another) 180 degrees 
currentAngle += 180; 
plane.transform = CATransform3DMakeRotation(currentAngle * M_PI/180.0f, 1.0f, 0.0f, 0.0f); 

dico "potrebbe", perché qualcosa nella descrizione realtà non carillon di come avrei aspetterebbe la trasformazione lavorare, e ci sono chiaramente alcune sottigliezze di implementazione che non propendo capire. Questo approccio potrebbe fallire. Ma è banalmente semplice, quindi probabilmente vale la pena provare.

+0

Grazie per il vostro aiuto. Purtroppo avevo provato già, solo che non ha funzionato perché i miei piani possono andare in entrambe le direzioni e la rotazione cumulativa si rovina. Come un riferimento, questo è quello che sto cercando di replicare: www.assalino.com (lo stack 3D dopo l'introduzione). L'ho fatto in AS3 ed è relativamente semplice: la chiave è in grado di cambiare la rotazione da -180 a 180 (ad esempio) senza animazione L'unico modo in cui ho trovato di farlo in Core Animation è cambiando la proprietà duration su 0 per quella modifica e quindi impostandola per l'animazione finale, ma si sovrappongono e non funziona. – Andre

+0

@Andre Il tuo Flash non ha funzionato per me (e davvero, la vita è troppo breve), quindi forse mi manca qualcosa, ma non sono sicuro di come i piani che vanno in entrambe le direzioni dovrebbero influenzare la rotazione cumulativa - se funziona in un modo, dovrebbe funzionare l'altro. In ogni caso, se questo trucco non funzionasse, penso che dovrai rinunciare all'animazione implicita e usare invece esplicito - puoi fermarti e avviarli a piacimento, specificare sequenze di valori e tempi, ricevere notifiche quando completano, ecc. – walkytalky

0

Per me funziona tale soluzione. Aggiungi un valore di rotazione intermedio per mostrare in quale direzione deve essere ruotata la vista. Quindi non hai bisogno di CAKeyframeAnimation.

if backwardDirection { 
    view.transform = CGAffineTransform(rotationAngle: -CGFloat.pi/2) 
    view.transform = CGAffineTransform(rotationAngle: 0) 
} else { 
    view.transform = CGAffineTransform(rotationAngle: -CGFloat.pi/2) 
    view.transform = CGAffineTransform(rotationAngle: -CGFloat.pi) 
} 
Problemi correlati