Я немного новичок в анимации и уже несколько дней экспериментирую с CoreAnimation. Не стесняйтесь предупредить меня, если этот вопрос не имеет смысла, но я пытаюсь добиться следующего. У меня есть три объекта:
- должно быть изображение, движущееся по заданному шаблону
- один должен быть UIImage, который меняет местами два изображения
- должен быть текст (CATextLayer?), Содержание которого меняется
Три действия должны происходить синхронно.
В качестве примера рассмотрим программу, показывающую синусоидальную функцию, как в ЭКГ, колеблющуюся между -1 и +1: первое изображение будет затем двигаться в соответствии с текущим значением (-1, -0.9, -0.8, ... 0, +0.1, +0.2, ... 1) изображение подкачки будет показывать "+" для положительных значений и "-" для отрицательных значений, а текст будет чередоваться между "Положительным" и "Отрицательным".
Я пытался с CAAnimationGroup, но я явно что-то упустил. Какой-то код:
{
// image that moves
CALayer *img1 = [CALayer layer];
img1.bounds = CGRectMake(0, 0, 20, 20);
img1.position = CGPointMake(x1,y1);
UIImage *img1Image = [UIImage imageNamed:@"image.png"];
img1.contents = (id)img1Image.CGImage;
// image that changes
CALayer *swap = [CALayer layer];
swap.bounds = CGRectMake(0, 0, 30, 30);
swap.position = CGPointMake(x2,y2);
NSString* nameswap = @"img_swap_1.png"
UIImage *swapImg = [UIImage imageNamed:nameswap];
// text
CATextLayer *text = [CATextLayer layer];
text.bounds = CGRectMake(0, 0, 100, 100);
text.position = CGPointMake(x3,y3);
text.string = @"Text";
// create animations
CGFloat duration = 0.2;
CGFloat totalDuration = 0.0;
CGFloat start = 0;
NSMutableArray* animarray = [[NSMutableArray alloc] init];
NSMutableArray* swapanimarray = [[NSMutableArray alloc] init];
NSMutableArray* textanimarray = [[NSMutableArray alloc] init];
float prev_x = 0;
float prev_y = 0;
// I get my values for moving the object
for (NSDictionary* event in self.events) {
float actual_x = [[event valueForKey:@"x"] floatValue];
float actual_y = [[event valueForKey:@"y"] floatValue];
// image move animation
CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"position"];
CGPoint startPt = CGPointMake(prev_x,prev_y);
CGPoint endPt = CGPointMake(actual_x, actual_y);
anim.duration = duration;
anim.fromValue = [NSValue valueWithCGPoint:startPt];
anim.toValue = [NSValue valueWithCGPoint:endPt];
anim.beginTime = start;
anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[animarray addObject:anim];
// image swap animation
CABasicAnimation *swapanim = [CABasicAnimation animationWithKeyPath:@"contents"];
swapanim.duration = duration;
swapanim.beginTime = start;
NSString* swapnamefrom = [NSString stringWithFormat:@"%@.png", prev_name];
NSString* swapnameto = [NSString stringWithFormat:@"%@.png", current_name];
UIImage *swapFromImage = [UIImage imageNamed:swapnamefrom];
UIImage *swapToImage = [UIImage imageNamed:swapnameto];
swapanim.fromValue = (id)(swapFromImage.CGImage);
swapanim.toValue = (id)(swapToImage.CGImage);
swapanim.fillMode = kCAFillModeForwards;
swapanim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
[swapanimarray addObject:swapanim];
//text animation
CABasicAnimation *textanim = [CABasicAnimation animationWithKeyPath:@"contents"];
textanim.duration = duration;
textanim.fromValue = @"Hey";
textanim.toValue = @"Hello";
textanim.beginTime = start;
[textanimarray addObject:textanim];
// final time settings
prev_x = actual_x;
prev_y = actual_y;
start = start + duration;
totalDuration = start + duration;
}
}
CAAnimationGroup* group = [CAAnimationGroup animation];
[group setDuration:totalDuration];
group.removedOnCompletion = NO;
group.fillMode = kCAFillModeForwards;
[group setAnimations:animarray];
CAAnimationGroup* swapgroup = [CAAnimationGroup animation];
[swapgroup setDuration:totalDuration];
swapgroup.removedOnCompletion = NO;
swapgroup.fillMode = kCAFillModeForwards;
[swapgroup setAnimations:swapanimarray];
CAAnimationGroup* textgroup = [CAAnimationGroup animation];
[textgroup setDuration:totalDuration];
textgroup.removedOnCompletion = NO;
textgroup.fillMode = kCAFillModeForwards;
[textgroup setAnimations:textanimarray];
[ball addAnimation:group forKey:@"position"];
[swap addAnimation:flaggroup forKey:@"position"];
[text addAnimation:textgroup forKey:@"contents"];
[self.layer addSublayer:ball];
[self.layer addSublayer:swap];
[self.layer addSublayer:text];
}
Теперь ... проблемы:
1) изображение свопа возвращается к оригиналу при каждом свопе. Итак, если я поменяю местами A-> B, я увижу, что он переходит от A к B в ожидаемый промежуток времени, но затем возвращается к A. Я прочитал несколько потоков на SO об этом, но не смог заставить его работать .
2) изменение строки текстового слоя по времени ... это возможно с этой инфраструктурой? По сути, я пытаюсь изменить текст и изображение подкачки, как только перемещается первое изображение, как описано в примере.
3) установка делегата для CABasicAnimation не имеет никакого эффекта, хотя это имеет место для CAAnimationGroup: в результате вы не можете управлять такими событиями, как animationDidStop, для каждой отдельной анимации, только для всей группы. Есть ли альтернативный способ сделать это?
4) следует из 3), возможно ли с помощью CAAnimationGroup перехватывать события для создания поведения остановки / запуска? Давайте предположим, что мне нужны кнопки воспроизведения / остановки и возобновление анимации с того места, где я ее оставил?
В качестве окончательного вопроса, я просто хотел бы знать, делал ли кто-то что-то подобное, и, что наиболее важно, действительно ли этот способ действий (с использованием CAAnimationGroup) является способом, или лучше использовать CAKeyFrameAnimation или что-то еще.