2009-02-18 9 views
8

Tengo varios CALayers que estoy tratando de animar a un nuevo zPosition con cada capa ligeramente retrasada de las demás.animando múltiples CALayers, pero no en el mismo espacio de tiempo

Cada animación debe tomar 0.25 segundos y comenzar 0.05 segundos después de que comenzó la animación anterior. Al final de cada animación, la capa se eliminará del árbol de capas.

He estado utilizando con éxito el método de delegado -animationDidStop:finished: para eliminar mis capas, ya que terminan, pero no he podido ordenar las animaciones correctamente.

¿Es posible programar animaciones de esta manera y cómo?

Respuesta

17

Todavía me gustaría escuchar otras sugerencias, pero creo que he resuelto esto.

Ahora estoy creando objetos específicos CAAnimation y especificando su propiedad beginTime. Estaba haciendo esto antes y no funcionaba, lo que finalmente me di cuenta es que para que la propiedad beginTime sea reconocida, la animación debe agregarse a CAAnimationGroup.

lo tanto, mi código es el siguiente:

NSArray *layers = /* layers to be animated away */ 
CGFloat startOffset = 0.01; 

for (NSInteger index = 0; index < layers.count; index++) { 
    CALayer *layer = [layers objectAtIndex:index]; 

    CABasicAnimation *zoomOut = [CABasicAnimation animationWithKeyPath:@"zPosition"]; 
    zoomOut.toValue = [NSNumber numberWithDouble:400.0]; 
    zoomOut.beginTime = index * startOffset; 

    CAAnimationGroup *group = [CAAnimationGroup animation]; 
    group.animations = [NSArray arrayWithObject:zoomOut]; 
    group.delegate = self; 

    [layer addAnimation:group forKey:@"zoomAway"]; 
} 
+0

También he estado buscando una respuesta a esto, y he intentado varias cosas diferentes. Pensé que sería posible crear un CAAnimationGroup compartido que todas las capas podrían compartir como un marco de tiempo de referencia, pero obviamente no funciona. Ahora creo que esta es probablemente la manera de hacerlo, pero también me encantaría escuchar a otros con más información sobre esto. – Felixyz

0

Gracias por compartir sus resultados, también descubrí que la propiedad BeginTime no funciona si se utiliza sin un grupo.

En mi caso, algunas de las configuraciones como BeginTime y Duration se ignoraron si se configuraron en CABasicAnimation, pero funcionaron si se configuraron directamente CAAnimationGroup.

14

He encontrado que la propiedad BeginTime realmente funciona sin poner las animaciones en un grupo si basas su valor como un delta del valor devuelto por la función CACurrentMediaTime() de QuartzCore.

p. Ej. anim.beginTime = CACurrentMediaTime() + 0.05;

+0

genial. No recuerdo haber intentado eso cuando lo hice originalmente. –

5

Me gustaría tener el representante de comentar, pero la razón de que el establecimiento de anim.beginTime a CACurrentMediaTime() obras se revela por algunos otros documentos:

AVCoreAnimationBeginTimeAtZero utilizar esta constante para establecer la animación beginTime propiedad del CoreAnimation para ser tiempo 0. La constante es un valor positivo pequeño, distinto de cero, que impide que CoreAnimation reemplace 0.0 con CACurrentMediaTime. Disponible en iOS 4.0 y posterior. Declarado en AVAnimation.h.

Por lo tanto, la configuración normal de beginTime en 0 es la abreviatura para configurarla en CACurrentMediaTime(). Entonces puedes usar el para escalonar el inicio de varios grupos.

+0

"Entonces la configuración normal de beginTime en 0 es una abreviatura para configurarla en CACurrentMediaTime()", wow, he estado buscando esta explicación, muchas gracias. – langtutheky

0

Swift 3

Resulta que usted puede hacer esto de forma relativamente sencilla haciendo lo siguiente:

var timeOffset:Double = 0 
let delay:Double = 0.1 
for layer in layers { 
    let a = CABasicAnimation(keyPath: "path" 
    a.fromValue = layer.ovalPathSmall.cgPath 
    a.toValue = layer.ovalPathLarge.cgPath 
    a.fillMode = kCAFillModeForwards 
    a.beginTime = CACurrentMediaTime() + timeOffset 
    a.duration = 0.3 
    a.isRemovedOnCompletion = true 
    layer.add(a, forKey: nil) 

    timeOffset += 0.3 + delay 
} 

Todas las capas están CALayer o CAShapeLayer, y en caso de que se pregunta qué ovalPathSmall y ovalPathLarge son:

ovalPathSmall = UIBezierPath(arcCenter: position, radius: smallRadius, startAngle: 0, endAngle: 2 * .pi, clockwise: true) 
ovalPathLarge = UIBezierPath(arcCenter: position, radius: largeRadius, startAngle: 0, endAngle: 2 * .pi, clockwise: true) 
Cuestiones relacionadas