Domanda

Sto lavorando con alcuni Core Animation per la prima volta e nel processo di attuazione di una carta da gioco che posso capovolgere in giro, ho deciso di utilizzare un CALayer per visualizzare il contenuto (non so come sto andando per ottenere due lati, ma questa è un'altra questione) e ho bisogno di essere in grado di capovolgerla, spostarlo, ecc ...

sto usando CATransaction con un certo successo - nel frammento di seguito, la carta si muove dal basso a sinistra in alto a sinistra e si ribalta. Il problema è che ho wan't a capovolgere il senso opposto, ma non so come dire che, "hey, si sta andando nella direzione sbagliata!"


[CATransaction begin]; 
[CATransaction setValue:[NSNumber numberWithFloat:2.0f] forKey:kCATransactionAnimationDuration];
myCard.position = CGPointMake(CGRectGetMidX(self.bounds)/2,CGRectGetMidY(self.bounds)/2);
myCard.transform = CATransform3DMakeRotation(M_PI, 1, 0, 0);
[CATransaction commit]; 

Una seconda domanda potrebbe essere: come posso arrivare a fare due trasforma in una volta? Ho provato due nidificazione CATransactions, ma la seconda solo sovrascrive il primo. Ho anche provato a cambiare il vettore per la rotazione sia 2D, come dire a ruotare intorno assi x ed y, ma non è pari a poco capovolgendolo per pi intorno a due assi singoli. Ecco il codice nidificato.


[CATransaction begin]; 
[CATransaction setValue:[NSNumber numberWithFloat:2.0f] forKey:kCATransactionAnimationDuration];
myCard.position = CGPointMake(CGRectGetMidX(self.bounds)/2,CGRectGetMidY(self.bounds)/2);
myCard.transform = CATransform3DMakeRotation(M_PI, 1, 0, 0); // rotate about x

  [CATransaction begin]; 
  [CATransaction setValue:[NSNumber numberWithFloat:1.0f] forKey:kCATransactionAnimationDuration];
  myCard.transform = CATransform3DMakeRotation(M_PI, 0, 1, 0); // rotate about y
  [CATransaction commit]; 

[CATransaction commit]; 

E qui è con blocchi UIView animazione dentro ... Ho cursori aggiunto per l'angolo, x, y, z per il vettore di rotazione, e t il tempo. La definizione si svolge nel tempo = 2t e ciascuna delle rotazioni dovrebbe prendere solo t ciascuna.

[CATransaction begin]; 
[CATransaction setValue:[NSNumber numberWithFloat:t * 2] forKey:kCATransactionAnimationDuration];
myCard.position = CGPointMake(CGRectGetMidX(self.view.bounds)/2,CGRectGetMidY(self.view.bounds)/2);

  [UIView beginAnimations:nil context:nil];
  [UIView setAnimationDuration:t];
  myCard.transform = CATransform3DMakeRotation(angle, x, y, z);
  [UIView commitAnimations]; 

  [UIView beginAnimations:nil context:nil];
  [UIView setAnimationDuration:t];
  [UIView setAnimationDelay:t];
  myCard.transform = CATransform3DMakeRotation(angle * 2, x, y, z);
  [UIView commitAnimations];

[CATransaction commit]; 

E questo è dove sono ora: E tutte le opere con una sola eccezione. Rovesci rotazione y (inizia a ruotare nella direzione opposta) quando la scheda arriva a pi / 2 e 3 * pi / 2. Si gira anche intorno all'asse x in questi punti. Ma xe grande z lavoro. Così vicino!

CGMutablePathRef thePath = CGPathCreateMutable();
CGPathMoveToPoint(thePath,NULL,CGRectGetMidX(self.view.bounds)/2,CGRectGetMidY(self.view.bounds)/2*3);
CGPathAddCurveToPoint(thePath,NULL,
                      CGRectGetMidX(self.view.bounds)/2,CGRectGetMidY(self.view.bounds)/2*2,
                      CGRectGetMidX(self.view.bounds)/2,CGRectGetMidY(self.view.bounds)/2*1.5,
                      CGRectGetMidX(self.view.bounds)/2,CGRectGetMidY(self.view.bounds)/2);
CAKeyframeAnimation *moveAnimation=[CAKeyframeAnimation animationWithKeyPath:@"position"];
moveAnimation.path=thePath;
CFRelease(thePath);

CABasicAnimation *xRotation;
xRotation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.x"];
xRotation.fromValue = [NSNumber numberWithFloat:0.0];
xRotation.toValue = [NSNumber numberWithFloat:x * angle * M_PI];

CABasicAnimation *yRotation;
yRotation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.y"];
yRotation.fromValue = [NSNumber numberWithFloat:0.0];
yRotation.toValue = [NSNumber numberWithFloat:y * angle * M_PI];

CABasicAnimation *zRotation;
zRotation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
zRotation.fromValue = [NSNumber numberWithFloat:0.0];
zRotation.toValue = [NSNumber numberWithFloat:z * angle * M_PI];

CAAnimationGroup *groupAnimation = [CAAnimationGroup animation];
groupAnimation.duration = t;
groupAnimation.removedOnCompletion = NO;
groupAnimation.fillMode = kCAFillModeForwards;
groupAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
groupAnimation.animations = [NSArray arrayWithObjects:moveAnimation, xRotation, yRotation, zRotation, nil];

[myCard addAnimation:groupAnimation forKey:@"animateCard"];
È stato utile?

Soluzione

Credo che ciò che si desidera in questo caso è quello di utilizzare un percorso chiave aiuto, come è descritto in questa risposta :

CABasicAnimation *rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.x"];
rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI];
rotationAnimation.duration = duration;
[myCard.layer addAnimation:rotationAnimation forKey:@"rotationAnimation1"];

che dovrebbe ruotare attorno all'asse X per la prima fase della vostra animazione. Per il secondo, credo che se si utilizza la seguente

CABasicAnimation *rotationAnimation2 = [CABasicAnimation animationWithKeyPath:@"transform.rotation.y"];
rotationAnimation2.toValue = [NSNumber numberWithFloat: M_PI];
rotationAnimation2.duration = duration2;
rotationAnimation2.cumulative = YES;
[myCard.layer addAnimation:rotationAnimation2 forKey:@"rotationAnimation2"];

dovrebbe rendere le animazioni cumulativa e può produrre l'effetto desiderato. Non ho provato io stesso, in modo da po 'di lavoro può essere richiesto per ottenere l'esatto risultato è necessario.

Quando si lavora con una trasformazione direttamente, Core Animation interpolerà la trasformazione dal valore corrente al specificato trasformare. Troverà il percorso più breve per arrivare a quel trasformare, che limiterà la direzione dell'animazione. Se si tenta di animare la stessa proprietà di trasformare due volte, il secondo valore semplicemente ignorare il primo, non unire le due trasformazioni insieme.

Tuttavia, quando si utilizza un percorso chiave aiuto come questo, Core Animation interpolerà tra il vostro angolo di partenza e l'angolo finale, in modo da poter invertire la direzione cambiando il segno dell'angolo fine. Ottimizza la variazione di valore dell'angolo, non la variazione del sottostante trasformata. Si dovrebbe anche essere in grado di combinare le animazioni sul percorso chiave, perché la trasformazione viene generato per voi sotto il cofano per ogni combinazione di manipolazioni percorso chiave.

Altri suggerimenti

Sto indovinando la lanciando su un asse è causato dal blocco del giunto cardanico accadendo all'interno della libreria di Apple. La soluzione semplice che funziona 99,999% del tempo è di non usare esatte 0, 90, 180, 270, e 360 ??gradi rotazioni. Ho visto cose come questa accada nel mio codice, ma mi basta usare qualcosa di simile (M_PI * 0.99) invece di M_PI. Questo è sempre un problema se si utilizza moltiplicatori matrice della scheda video con angoli di Eulero.

Per applicare più trasformazioni, allo stesso tempo, è possibile nidificare loro. Questo funziona esattamente come moltiplicare le matrici in OpenGL.

// translate and scale at the same time
float scale = 1.6;
CATransform3D scaleMatrix = CATransform3DMakeScale(scale, scale, 1);
CATransform3D finalMatrix = CATransform3DTranslate(scaleMatrix, frame.size.width/scale, frame.size.height/scale, 0);
CABasicAnimation* animBottomTrans = [CABasicAnimation animationWithKeyPath:@"transform"];
[animBottomTrans setFromValue:[NSValue valueWithCATransform3D:finalMatrix]];
[animBottomTrans setToValue:[NSValue valueWithCATransform3D:CATransform3DIdentity]];
[animBottomTrans setDuration:duration];
[myLayer addAnimation:animBottomTrans forKey:@"transform"];

Si ricorda che dal momento che questi sono annidati bisogna fare i conti con il precedente trasformare in eventuali trasformazioni che vengono dopo di esso. In questo codice devo cambiare la quantità Tradussi perché ho già scalato. Se si ruota 90degrees sull'asse Z e poi ruotare di 90 gradi sull'asse y, si è efficace solo ruotata sulla Z e X axises (la rotazione z scambia il tuo x ed assi Y).

La risultante trasformare è la stessa: (CGAffineTransform){-1,0,0,-1,0,0}. Core Animation raccoglie la rotazione più breve che farà il trucco, e il valore predefinito è ruotando in senso orario (credo).

Il modo più semplice per ruotare l'altro modo è quello di ruotare da quasi -M_PI (io non so esattamente quanto vicino si può ottenere prima di decidere di ruotare il modo "sbagliato").

Il modo più complicato è quello di suddividerlo in due rotazioni: uno da 0 a -M_PI / 2 e uno da -M_PI / 2 per -M-PI. Penso che si possa impostare un ritardo di animazione per rendere questo accada ...

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top