Как успешно анимировать несколько слоев CALay одновременно? - PullRequest
3 голосов
/ 29 июля 2011

Я успешно анимирую один слой, чтобы изменить его положение по произвольному пути на моем экране. Сейчас я пытаюсь повторить эту анимацию несколько раз, чтобы создать иллюзию того, что что-то огибает угол. Я поместил код в CATransaction и поместил его в цикл, увеличивая начальную позицию для каждой итерации цикла, затем зафиксировал CATransaction после цикла. Эффект, который я вижу, тот же, если код не был в цикле (то есть анимируется только один слой), тогда в конце анимации появляются все слои (до того, как мой делегат удалит их в конце анимации в animationDidStop )

Код, который я написал, выглядит следующим образом:

NSArray* path = [board caclulatePath:s];
    [CATransaction begin];
    [CATransaction setValue:[NSNumber numberWithFloat:([path count] * 0.25)] forKey:kCATransactionAnimationDuration];
    for (int i = 0; i < 20; i++)
    {
        CALayer* laserLayer = [CALayer layer];
        laserLayer.bounds = CGRectMake(s.frame.origin.x, s.frame.origin.y + (10*i), 20, 10);
        laserLayer.position = CGPointMake(s.frame.origin.x + (s.frame.size.width / 2), s.frame.origin.y + (s.frame.size.height / 2) + (10*i));
        laserLayer.contents = (id)[UIImage imageNamed:@"Laser.png"].CGImage;
        [self.layer addSublayer:laserLayer];

        CAKeyframeAnimation* anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
        anim.values = path;
        anim.duration = ([path count] * 0.25);
        anim.removedOnCompletion = NO;
        anim.delegate = self;
        anim.rotationMode = kCAAnimationRotateAuto;
        [anim setValue:@"Fire" forKey:@"Action"];
        [anim setValue:laserLayer forKey:@"Layer"];
        [laserLayer addAnimation:anim forKey:nil];
    }
    [CATransaction commit];

где [board caclulatePath: s] возвращает NSArray * из NSValues, представляющих CGPoints.

Как мне добиться эффекта, которого я добиваюсь (а это несколько копий laser.png по одному и тому же пути)? [Laser.png - красный квадрат размером 20 на 20 пикселей];

Ответы [ 2 ]

2 голосов
/ 29 июля 2011

Фактическая проблема заключалась в том, что каждый слой БЫЛ по одному и тому же пути, в одно и то же время ... Решением было отключить каждый Слой / Анимацию после задержки (someSmallFractionOfTime * i), где я увеличивался.

Итак, я извлек часть анимации как новую функцию / метод / сообщение (как бы она ни называлась)

- (void) kickoffLaserAnimationWithPath: (NSArray *) path  {
CGPoint start = [(NSValue*)[path objectAtIndex:0] CGPointValue];
CALayer* laserLayer = [CALayer layer];
laserLayer.bounds = CGRectMake(start.x, start.y, 20, 10);
laserLayer.position = CGPointMake(start.x, start.y);
laserLayer.contents = (id)[UIImage imageNamed:@"Laser.png"].CGImage;
[self.layer addSublayer:laserLayer];

CAKeyframeAnimation* anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
anim.values = path;
anim.duration = ([path count] * laserSpeed);
anim.removedOnCompletion = NO;
anim.delegate = self;
anim.rotationMode = kCAAnimationRotateAuto;
[anim setValue:@"Fire" forKey:@"Action"];
[anim setValue:laserLayer forKey:@"Layer"];
[laserLayer addAnimation:anim forKey:nil];
isAnimating = YES;

}

и назвал его внутри цикла следующим образом:

NSArray* path = [board caclulatePath:s];
    [CATransaction begin];
    [CATransaction setValue:[NSNumber numberWithFloat:([path count] * laserSpeed)] forKey:kCATransactionAnimationDuration];
    float numBetweenPoints = (float)((float)s.frame.size.height / (float)10) * 2;
    float delay = (laserSpeed / numBetweenPoints);
    for (int i = 0; i < [path count]; i++)
    {
        [self performSelector:@selector(kickoffLaserAnimationWithPath:) withObject:path afterDelay:(delay*i)];

    }
    [CATransaction commit];

Вуаля ...

2 голосов
/ 29 июля 2011

Взгляните на CAAnimationGroup . Я думаю, что это может удовлетворить вашу проблему.

...