2012-02-03 11 views
10

Mam scrollView z włączoną stronicowaniem i liczbą N stron, które są UIViews jako subviews z scrollView.W jaki sposób mogę łączyć Core Animations dla różnych warstw jeden po drugim?

Próbuję wykonać następujące czynności:

użytkownik przewija do strony numer n. W tym momencie 7 KALKarterów, które zostały poprzednio dodane do numeru strony n (tj. Do strony [[scrollView subviews] objectAtIndex: n-1] subwarstwy .layer) pojawią się jeden po drugim.

Ale nie mogę wymyślić, jak sprawić, aby CALayers zanikły kolejno.Tak daleko, wypróbowałem następujące 3 podejścia z metody delegata mojego kontrolera: (załóżmy mam tablicę do warstw i ich nieprzezroczystość został ustawiony na 0 po utworzeniu)

- (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]; 
    } 
} 

Ale nic nie działa. Gdy użytkownik przewinie do właściwej strony, wszystkie warstwy staną się widoczne od razu, bez znacznego zanikania i zdecydowanie nie w żadnej kolejnej kolejności.

Wszelkie pomysły?

Odpowiedz

18

Faktycznie, okazuje się, że klucz jest uzyskanie aktualnego czasu pod względem układu odniesienia i dodanie jakiegokolwiek przesunięcia czasowego do tej chwili obecnej. Działa to również w przypadku niezgrupowanych animacji.

Na przykład, coś w rodzaju tego kodu spowoduje brak warstwy (zakłada się, że można przechowywać go w niektórych tablicy), kolejno pojawiania jeden za drugim, z których każde ma .8 sek .:

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]; 

W powyższym przypadku układ odniesienia jest po prostu bieżącym czasem, w którym odbywają się wywołania.

5

Właściwość beginTime tylko z CAAnimation wydaje się działać tylko wtedy, gdy CAAnimation jest częścią CAAnimationGroup. Myślę, że musisz również ustawić właściwość duration na tyle dużą, aby mogła trwać do zakończenia końcowej animacji.

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

0

w Swift 3 (warstwy jest tablicą CALayer lub 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 
} 

A w przypadku, gdy zastanawiasz się co ovalPathSmall i ovalPathLarge są:

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) 
Powiązane problemy