2009-12-15 18 views
32

Какой самый элегантный и модульный способ анимации анимации в контексте Core Animation?Анимация анимации цепей анимации

Я имею в виду, чтобы сделать анимацию, которая начинается только тогда, когда другие законченным (например, изменение position, а затем opacity) .. нормальный подход непосредственно изменить свойство:

layer.position = new_point; 
layer.opacity = 0.0f; 

, но это будет делать их в том же время. Я хочу, чтобы один подождал другого.

А как насчет цепочки анимации для разных объектов? Я читал о CATransaction используется как:

[CATransaction begin] 
layer1.property = new_property; 
[CATransaction begin] 
layer2.property2 = new_property2; 
[CATransaction commit]; 
[CATransaction commit]; 

, но это не похоже на работу ..

ответ

73

Вы также можете использовать анимационную группировку и использовать поле beginTime анимации. Попробуйте что-то вроде этого:

CABasicAnimation *posAnimation = [CABasicAnimation animationWithKeyPath:@"position"]; 
[posAnimation setFromValue:[NSNumber numberWithFloat:0.0]]; 
[posAnimation setToValue:[NSNumber numberWithFloat:1.0]]; 
// Here's the important part 
[posAnimation setDuration:10.0]; 
[posAnimation setBeginTime:0.0]; 

CABasicAnimation *borderWidthAnimation = [CABasicAnimation animationWithKeyPath:@"borderWidth"]; 
[borderWidthAnimation setFromValue:[NSNumber numberWithFloat:0.0]]; 
[borderWidthAnimation setToValue:[NSNumber numberWithFloat:1.0]]; 
// Here's the important part 
[borderWidthAnimation setDuration:10.0]; 
[borderWidthAnimation setBeginTime:5.0]; 

CAAnimationGroup *group = [CAAnimationGroup animation]; 
[group setDuration:10.0]; 
[group setAnimations:[NSArray arrayWithObjects:posAnimation, borderWidthAnimation, nil]]; 

[layer addAnimation:group forKey:nil]; 

Обратите внимание, что продолжительность всей анимации составляет 10 секунд. Первый начинается со второго 0, а второй начинается через 5 секунд.

+9

к сведению, что это здорово, но будет работать только для анимации, применяемых к одному слой. – nielsbot

+0

Также, если вы хотите вызвать метод, как только закончите первую анимацию, вы не сможете. animationDidStop вызывается только после завершения всей группы. – durazno

+0

key path '" position "' является 'CGPoint', который должен быть закодирован с помощью NSValue (а не' NSNumber'). – wcochran

0

Я не верю, что вы можете «вкладывания» CA анимации, как у вас есть в вашем примере.

Для анимации необходимо указать делегат и поставить второй «переход» в селектор делегата animationDidStop:finished:.

Возможно, вы хотите посмотреть на Apple Animation Types & Timing Programming Guide.

5

Как отметил Мэтт, вы можете создавать группы анимации, которые состоят из разных анимаций для одного и того же слоя с разными временами начала. Вы можете также установить делегат для автономных CAAnimation объектов или CAAnimation групп и как каждая анимация заканчивается это будет вызвать animationDidStop:finished: метод делегата (обратите внимание, что анимации, которые являются частью группы не будет вызывать animationDidStop:finished: метод их делегат.

Я придумал отличный трюк, который делает использование метода CAAnimation animationDidStop:finished: более мощным. Я использую метод setValue:forKey:, чтобы добавить блок кода в отдельную анимационную или анимационную группу с ключом @ "animationCompletionBlock". Затем я пишу общий animationDidStop:finished: метод, который проверяет только что завершенную анимацию для клавиши @ «animationCompletionBlock», и если она ее найдет, выполните там код кода.

Взгляните на этот проект на GitHub для рабочего примера этой методики:

CAAnimation demo with completion blocks

Вам также Установить группу анимации внутри блока

[CATransaction begin]; 
//... 
[[CATransaction commit]; 

, как вы предложили. Когда вы это сделаете, вы можете использовать метод класса CATransactionsetCompletionBlock:, чтобы вызвать блок кода, когда все анимации в текущей группе транзакций завершены. Блок завершения для одной транзакции может затем инициировать следующую транзакцию.

0

То, что я всегда предпочитал установки начала и окончания каждой анимации по отдельности это:

Я использовал A2DynamicDelegate (развитие которого сейчас происходит в BlocksKit -Repo, кто знает, почему < < _) в реализовать свойство completeBlock в категории по CAAnimation.

Это позволило мне делать такие вещи, как это:

CAAnimation *a = ... 
CAAnimation *b = ... 
CAAnimation *c = ... 

a.completionHandler = ^{ 
    [self.layer addAnimation:b forKey:@"foo"]; 
    [self.layer addAnimation:c forKey:@"bar"]; 
}; 

Гораздо более гибким :)

Я загрузил свой код для обработчика завершения here. Однако обратите внимание на уведомление в файле заголовка. Я действительно смущен, почему метод не называется.

-1

Без включая все «фокусы» до моего «набора инструментов», этот пример не напрямую копировать/pastable ... но он показывает очень простую стратегию «приковано» анимация ..

CATransform3D trans = m34(); // define chain-wide constants. 
// Name your "stack". My "nextObject" returns arr[i]->done == nil. 
NSArray *layerStack = layer.sublayers; 
//define a block, that "takes" a layer as it's argument. 
void(^__block ChainBlock)(CALayer*) = ^(CALayer *m) { 
// animations, transforms, etc for each inividual "step". 
    [m animate:@"transform" 
      // These are just NSValue-wrapped CAT3D's 
      from:AZV3d(CATransform3DRotate(trans, 0,1,0,0)) 
      to:AZV3d(CATransform3DRotate(trans,1.5,1,0,0)) 
      time:2 // total time == each step * layerStack.count 
     eased:kCAMediaTimingFunctionEaseOut 
    completion:^{ // In completion, look for "next" layer. 
        CAL* m2 = [layers nextObject]; 
// If there is "another" layer, call this block, again... with it. 
         if (m2) chainAnis(m2); 
// Otherise,you're done. Cleanup, toggle values, whatevs. 
        else self.finishedProperty = YES; 
    }]; 
}; 
// Give the block we just defined your "first" layer. 
ChainBlock(layerStack[0]); // It will recursively feed itself. 

Это очевидно, зависит от некоторой «внешней магии», но концепция проста и устраняет (через зависимости) необходимость «иметь дело с» ЛЮБОЙ вид валовой делегации . В частности, категории animate:from:to:time:easing:completion и т. Д. Относятся к отличным FunSize Framework, on Github.

0

Я провернуть это с помощью метода setCompletionBlock определить замыкание, которое вызывает следующую анимацию, когда первая одна закончена:

[CATransaction begin] 
layer1.property = new_property; 
CATransaction.setCompletionBlock { 
    [CATransaction begin] 
    layer2.property2 = new_property2; 
    [CATransaction commit]; 
} 
[CATransaction commit]; 
Смежные вопросы