transiciones profesionales presets plantillas plantilla para intros gratis fotos efectos editables como animar animacion after ios iphone animation core-animation calayer

ios - profesionales - Comprender la pausa y reanudar la animación en una capa



presets para after effects gratis (3)

De los docs :

hora de inicio

beginTime Especifica la hora de inicio del receptor en relación con su objeto principal, si corresponde. (necesario)

Aquí hay una gran explicación de esto tomado de here :

Si una animación está en un grupo de animación, beginTime es el desplazamiento desde el principio de su objeto principal: el grupo de animación. Entonces, si el tiempo de inicio de la animación es 5, comienza 5 segundos después de que comience el grupo de animación.

Si una animación se agrega directamente a una capa, beginTime sigue siendo el desplazamiento desde el principio de su objeto principal: la capa. Pero como el comienzo de una capa está en el pasado 1, no puedo simplemente establecer el tiempo de inicio en 5 para retrasar la animación 5 segundos, ya que 5 segundos después del comienzo de una capa es probablemente un tiempo pasado. Lo que generalmente quiero es un retraso relativo a cuando la animación se agrega a la capa, indicada por addTime.

Este es el código de la pregunta con una adición de registros:

- (IBAction)start:(UIButton *)sender { [UIView animateWithDuration:10 animations:^() {//Move square to x=300 }completion:^(BOOL finished){}]; } - (IBAction)pause:(UIButton *)sender { CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil]; layer.speed = 0.0; layer.timeOffset = pausedTime; NSLog(@"pausedTime: %f",pausedTime); } - (IBAction)resume:(UIButton *)sender { CFTimeInterval pausedTime = [layer timeOffset]; layer.speed = 1.0; layer.timeOffset = 0.0; layer.beginTime = 0.0; NSLog(@"CACurrentMediaTime: %f",[layer convertTime:CACurrentMediaTime() fromLayer:nil]); CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime; NSLog(@"timeSincePause: %f",timeSincePause); layer.beginTime = timeSincePause; }

Salida:

pausedTime: 20000 CACurrentMediaTime: 20005 timeSincePause: 5 // <- that''s your begin time. When you hit resume you want to begin the animation from that relative time.

Para resumir todo esto,

La duración de la animación es un total de 10, detuve la animación en 5 y también quiero que sea mi tiempo de inicio cuando reanudo la animación.

Por lo tanto, guardo el tiempo de pausa y lo resto de mi tiempo actual para obtener el tiempo de animación relativo que ha pasado.

Estoy estudiando Animación en la Guía de programación de animaciones básicas y me quedo atascado al comprender la pausa y reanudar la animación en una capa.

El documento me dice cómo pausar y reanudar la animación sin una explicación clara. Creo que la clave es entender qué es el método timeOffset y beginTime de CAlayer .

Este código es pausar y reanudar la animación. En el método resumeLayer , layer.beginTime = timeSincePause; Esta línea realmente me confunde.

-(void)pauseLayer:(CALayer*)layer { CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil]; layer.speed = 0.0; layer.timeOffset = pausedTime; } -(void)resumeLayer:(CALayer*)layer { CFTimeInterval pausedTime = [layer timeOffset]; layer.speed = 1.0; layer.timeOffset = 0.0; layer.beginTime = 0.0; CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime; layer.beginTime = timeSincePause; }

Cualquier ayuda será apreciada.


En el archivo de cabecera de CAMediaTiming, podemos ver estos códigos:

/* The begin time of the object, in relation to its parent object, if * applicable. Defaults to 0. */ @property CFTimeInterval beginTime; /* The basic duration of the object. Defaults to 0. */ @property CFTimeInterval duration; /* The rate of the layer. Used to scale parent time to local time, e.g. * if rate is 2, local time progresses twice as fast as parent time. * Defaults to 1. */ @property float speed; /* Additional offset in active local time. i.e. to convert from parent * time tp to active local time t: t = (tp - begin) * speed + offset. * One use of this is to "pause" a layer by setting `speed'' to zero and * `offset'' to a suitable value. Defaults to 0. */ @property CFTimeInterval timeOffset;

Lo importante es la fórmula:

t = (tp - comenzar) * velocidad + desplazamiento

Esta fórmula define cómo la hora global (o la hora principal, tp) se asigna a la hora local de la capa. Y esta fórmula puede explicar todo de los códigos listados:

  1. En el momento A, la animación está en pausa. Después de establecer la velocidad = 0, y timeOffset = pauseTime, la hora local de la capa es igual a pauseTime. Y la hora local no aumentará más porque la velocidad = 0;
  2. En el momento B, se reanuda la animación. Después de establecer la velocidad = 1.0, timeOffset = 0, beginTime = 0, la hora local de la capa es igual a la hora global (o tp) que es (timePause + timeSinacePause). Pero necesitamos que la animación comience desde el punto de tiempo #A, así que configuramos beginTime = timeSincePaused, y luego la hora local de la capa es igual a timePause. De causa, esto incurre en que la animación continúe desde el punto en pausa.


Hagamos una prueba en las dos propiedades de una capa: beginTime y timeOffset .

Requisito previo

Obtenemos el espacio de tiempo de CALayer utilizando [layer convertTime:CACurrentMediaTime() fromLayer:nil]

1 、 Asignar 5.0 al tiempo de beginTime la capa (el tiempo de beginTime es 0 antes):

NSLog(@"CACurrentMediaTime:%f", [t1.layer convertTime:CACurrentMediaTime() fromLayer:nil]) ; t1.layer.beginTime = 5.0 ; NSLog(@"CACurrentMediaTime:%f",[t1.layer convertTime:CACurrentMediaTime() fromLayer:nil]) ;

el registro de resultados es:

2014-01-15 11:00:33.811 newUserInterface[1404:70b] CACurrentMediaTime:7206.884498 2014-01-15 11:00:33.811 newUserInterface[1404:70b] CACurrentMediaTime:7201.885088

El resultado muestra que si agrego 5.0 en beginTime , el tiempo de la capa será menos 5.0. Si una animación está en vuelo, agregar 5.0 en beginTime provocará que la animación vuelva a hacer la animación hace 5.0 segundos.

2 、 Asigne 5.0 a timeOffset la capa ( timeOffset es 0 antes):

NSLog(@"CACurrentMediaTime:%f", [t1.layer convertTime:CACurrentMediaTime() fromLayer:nil]) ; t1.layer.timeOffset = 5.0 ; NSLog(@"CACurrentMediaTime:%f",[t1.layer convertTime:CACurrentMediaTime() fromLayer:nil]) ;

el resultado es:

2014-01-15 11:09:07.757 newUserInterface[1449:70b] CACurrentMediaTime:7720.851464 2014-01-15 11:09:07.758 newUserInterface[1449:70b] CACurrentMediaTime:7725.852011

El resultado muestra que si agrego 5.0 en timeOffset , el tiempo de la capa agregará 5.0. Si una animación está en vuelo, agregar 5.0 en timeOffset causará que la animación salte a la animación que haría 5.0 segundos más tarde.

Comprender la pausa y reanudar la animación en una capa

Aquí hay un ejemplo, t1 es una subvista de la vista raíz de UIViewController. Hago una animación en t1 que anima la posición de t1.layer .

Si se agrega una animación a una capa, la capa calculará cuándo animar la animación de acuerdo con el tiempo de beginTime la animación, si el tiempo de beginTime es 0, lo animará de inmediato.

CABasicAnimation * b1 = [CABasicAnimation animationWithKeyPath:@"position"] ; b1.toValue = [NSValue valueWithCGPoint:CGPointMake(160.0, 320.0)] ; b1.duration = 10.0f ; [t1.layer addAnimation:b1 forKey:@"pos"] ; NSLog(@"CACurrentMediaTime:%f", [t1.layer convertTime:CACurrentMediaTime() fromLayer:nil]) ;

muestra el registro 2014-01-15 11:25:53.975 newUserInterface[1530:70b] CACurrentMediaTime:8727.108740 , lo que significa que la animación comenzará en 8727 y se detendrá en 8727 + 10 en el espacio de tiempo de t1.layer.

Cuando la animación está en vuelo, y la - (void)pauseLayer:(CALayer*)layer método de - (void)pauseLayer:(CALayer*)layer .

layer.speed = 0.0; provocará que la capa se detenga y el tiempo de la capa se establecerá en 0. (Lo sé porque al establecer layer.speed en 0, inmediatamente busco la hora de la capa y la registro)

layer.timeOffset = pausedTime; agregará pauseTime al tiempo de la capa (asumiendo que layer.timeOffset sea 0), ahora el tiempo de la capa es pausedTime.

- (void)pauseLayer:(CALayer *)layer { CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil]; // pauseTime is the time with respect to layer''s time space layer.speed = 0.0; // layer''s local time is 0 layer.timeOffset = pausedTime; // layer''s local time is pausedTime, so animation stop here }

Luego reanudaré la animación utilizando el método de - (void)resumeLayer:(CALayer*)layer .

-(void)resumeLayer:(CALayer*)layer { CFTimeInterval pausedTime = [layer timeOffset]; layer.speed = 1.0; layer.timeOffset = 0.0; layer.beginTime = 0.0; CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime; layer.beginTime = timeSincePause; }

Si detengo la animación en 8727 + 1 (significa la animación animada durante 1 segundo), en el método layer.speed = 0 , layer.speed = 0 establecerá el tiempo de la capa en 0 y layer.timeOffset = pausedTime; agregará tiempo de pausa en el tiempo de la capa, por lo que el tiempo de la capa es tiempo de pausa.

Espera un momento, vamos a tener un resumen ahora. layer.speed es 0.0, ''layer.timeOffset'' es igual a pausedTime que es 8727 + 1 y el tiempo de layer es pausedTime también. Por favor ten en cuenta que pronto los usaremos.

Continuemos, layer.speed = 1.0; la animación en 8727 + 11 con el método layer.speed = 1.0; , layer.speed = 1.0; agregará 8727 + 11 en el tiempo de la capa, por lo que el tiempo de la capa es 8727 + 1 + 8727 + 11, layer.timeOffset = 0.0; causa el tiempo de la capa menos 8727 + 1 porque layer.timeOffset es 8727 + 1 antes, la hora local de la capa es 8727 + 11 ahora. timeSincePause es (8727 + 11-8727-1) = 10.

layer.beginTime = timeSincePause; hace que el tiempo de la capa sea menos 10. Ahora, el tiempo local de la capa es 8727 + 1, que es el momento en que hice una pausa en la animación.

Te mostraré el código y el registro:

- (void)pauseLayer:(CALayer *)layer { NSLog(@"%f", CACurrentMediaTime()) ; NSLog(@"pauseLayer begin:%f", [t1.layer convertTime:CACurrentMediaTime() fromLayer:nil]) ; CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil] ; layer.speed = 0.0 ; NSLog(@"pauseLayer after set speed to 0:%f",[t1.layer convertTime:CACurrentMediaTime() fromLayer:nil]) ; layer.timeOffset = pausedTime ; NSLog(@"pauseLayer after set timeOffset:%f",[t1.layer convertTime:CACurrentMediaTime() fromLayer:nil]) ; } - (void)resumeLayer:(CALayer *)layer { NSLog(@"%f", CACurrentMediaTime()) ; NSLog(@"resumeLayer begin:%f",[t1.layer convertTime:CACurrentMediaTime() fromLayer:nil]) ; CFTimeInterval pausedTime = layer.timeOffset ; layer.speed = 1.0 ; NSLog(@"resumeLayer after set speed to 1:%f",[t1.layer convertTime:CACurrentMediaTime() fromLayer:nil]) ; layer.timeOffset = 0.0; NSLog(@"resumeLayer after set timeOffset to 0:%f",[t1.layer convertTime:CACurrentMediaTime() fromLayer:nil]) ; layer.beginTime = 0.0 ; NSLog(@"resumeLayer after set beginTime to 0:%f",[t1.layer convertTime:CACurrentMediaTime() fromLayer:nil]) ; CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime ; layer.beginTime = timeSincePause ; NSLog(@"resumeLayer after set beginTime to timeSincePause:%f",[t1.layer convertTime:CACurrentMediaTime() fromLayer:nil]) ; }

Iniciar sesión:

2014-01-15 13:14:34.157 newUserInterface[1762:70b] 15247.550325 2014-01-15 13:14:34.158 newUserInterface[1762:70b] pauseLayer begin:15247.550826 2014-01-15 13:14:34.158 newUserInterface[1762:70b] pauseLayer after set speed to 0:0.000000 2014-01-15 13:14:34.159 newUserInterface[1762:70b] pauseLayer after set timeOffset:15247.551284 2014-01-15 13:14:40.557 newUserInterface[1762:70b] 15253.950505 2014-01-15 13:14:40.558 newUserInterface[1762:70b] resumeLayer begin:15247.551284 2014-01-15 13:14:40.558 newUserInterface[1762:70b] resumeLayer after set speed to 1:30501.502810 2014-01-15 13:14:40.559 newUserInterface[1762:70b] resumeLayer after set timeOffset to 0:15253.952031 2014-01-15 13:14:40.559 newUserInterface[1762:70b] resumeLayer after set beginTime to 0:15253.952523 2014-01-15 13:14:40.560 newUserInterface[1762:70b] resumeLayer after set beginTime to timeSincePause:15247.551294

Otra pregunta está en el método resumeLayer : ¿por qué no combinar las dos líneas de asignación en una layer.beginTime = timeSincePause; , la razón está en [layer convertTime:CACurrentMediaTime() fromLayer:nil] , el valor del resultado está relacionado con layer.beginTime.

layer.beginTime = 0.0; CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime; layer.beginTime = timeSincePause;

A decir verdad, todavía no sé cómo funciona la animación, lo que estoy haciendo es analizar el resultado, no es una buena solución. Estoy muy contento de que cualquiera que tenga ideas sobre esto pueda compartir. ¡Gracias!