Как успешно анимировать несколько слоев CALay одновременно?
Я успешно анимирую один слой, чтобы изменить его положение по произвольному пути на моем экране. Сейчас я пытаюсь повторить эту анимацию несколько раз, чтобы создать иллюзию того, что что-то огибает угол. Я поместил код в 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 ответа
Фактическая проблема заключалась в том, что каждый слой следовал по одному и тому же пути в одно и то же время... Решением было отключить каждый слой / анимацию после задержки (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];
Вуаля...
Взгляните на CAAnimationGroup. Я думаю, что это может удовлетворить вашу проблему.