2012-02-03 13 views
10

Tengo un scrollView con paginación habilitada y un número N de páginas, que son UIViews como subvistas de scrollView.¿Cómo puedo encadenar Core Animations para diferentes capas una después de la otra?

estoy tratando de hacer lo siguiente:

usuario se desplaza a número de página n. En ese momento, 7 CALayers que se agregaron previamente al número de página n (es decir, a la página [[scrollView subviews] objectAtIndex: n-1] .layer subLayers]) se desvanecen, uno tras otro.

Pero no puedo entender cómo hacer que los CALayers se desvanezcan secuencialmente. Hasta ahora, he intentado los siguientes 3 enfoques del método delegado de mi controlador: (supongo que tengo una matriz para las capas y que su opacidad se estableció en 0 al crearlo)

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView 
{ 
    int pageNumber = floor(self.scrollView.contentOffset.x/self.scrollView.frame.size.width); 
    if(pageNumber == (n-1)) 
    { 
    int timeOffset = 0; 

    [CATransaction begin]; 
    for(CALayer *layer in layerArray) 
    { 
     CABasicAnimation *a = [CABasicAnimation animationWithKeyPath:@"opacity"]; 
     a.duration = 6; 
     a.beginTime = timeOffset++; 
     a.fromValue = [NSNumber numberWithFloat:0.]; 
     a.toValue = [NSNumber numberWithFloat:1.]; 

     [layer addAnimation:a forKey:nil]; 
    } 
    [CATransaction commit]; 
    } 
} 

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView 
{ 
    int pageNumber = floor(self.scrollView.contentOffset.x/self.scrollView.frame.size.width); 
    if(pageNumber == (n-1)) 
    { 
    int timeOffset = 0; 

    [CATransaction begin]; 
    for(CALayer *layer in layerArray) 
    { 
     CABasicAnimation *a = [CABasicAnimation animation]; 
     a.duration = 6; 
     a.beginTime = timeOffset++; 
     [layer addAnimation:a forKey:@"opacity"]; 
     [layer setOpacity:1]; 
    } 
    [CATransaction commit]; 
    } 
} 


- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView 
{ 
    int pageNumber = floor(self.scrollView.contentOffset.x/self.scrollView.frame.size.width); 
    if(pageNumber == (n-1)) 
    { 
    int timeOffset = 0; 


    for(CALayer *layer in layerArray) 
    { 
     [CATransaction begin]; 
     CABasicAnimation *a = [CABasicAnimation animation]; 
     a.duration = 6; 
     a.beginTime = timeOffset++; 
     [layer addAnimation:a forKey:@"opacity"]; 
     [layer setOpacity:1]; 
    } 

    for(CALayer *layer in layerArray) 
     [CATransaction commit]; 
    } 
} 

Pero ninguno parece funcionar. Cuando el usuario se desplaza a la página correcta, todas las capas se vuelven visibles a la vez, sin mucho fundido y definitivamente no en orden secuencial.

¿Alguna idea?

Respuesta

18

En realidad, resulta que la clave es obtener la hora actual en términos de un marco de referencia y añadiendo cualquier desplazamiento a la hora de tiempo. Esto funciona también para animaciones no agrupadas.

Por ejemplo, algo a lo largo de las líneas de este código podría causar n capas (que se supone almacenado en algunos array) secuencialmente fundido de entrada una tras otra, cada uno tomando .8 secs .:

CGFloat timeOffset = 0; 
    [CATransaction begin]; 
    for(CALayer *layer in layers) 
    { 
    CABasicAnimation *a = [CABasicAnimation animationWithKeyPath:@"opacity"]; 
    a.fromValue = [NSNumber numberWithFloat:0.]; 
    a.toValue = [NSNumber numberWithFloat:1.]; 
    a.fillMode = kCAFillModeForwards; 
    a.beginTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil] + timeOffset; 
    a.duration = .8; 
    a.removedOnCompletion = NO; 
    [layer addAnimation:a forKey:nil]; 

    timeOffset += .8; 
    } 
    [CATransaction commit]; 

En el caso anterior, el marco de referencia es simplemente el momento actual en que tienen lugar las invocaciones.

5

La propiedad beginTime de un CAAnimation solo parece funcionar si el CAAnimation es parte de un CAAnimationGroup. Creo que también necesitará configurar la propiedad duration del CAAnimationGroup lo suficientemente grande como para durar hasta que finalice su animación final.

https://stackoverflow.com/a/563486/77567

0

En Swift 3 (capas es un conjunto de CALayer o CAShapeLayer)

var timeOffset:Double = 0 
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 = false 
    layer.add(a, forKey: nil) 

    timeOffset += 0.3 
} 

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