2009-12-15 9 views
32

코어 애니메이션 컨텍스트에서 애니메이션을 연결하는 가장 우아하고 모듈 식 방법은 무엇입니까?코어 애니메이션 애니메이션 연결

나는 시작하는 애니메이션을 의미 바로 그 때 다른 완료 (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

키 경로''위치''는'NSValue' ('NSNumber'가 아닙니다)로 인코딩 될 필요가있는'CGPoint'입니다. – wcochran

0

을 나는 믿지 않는다 당신이 당신이 당신의 예에서 가지고 할 수있는 '둥지'CA 애니메이션.

애니메이션의 경우 대리자을 지정하고 대리자의 animationDidStop:finished: 선택자 내에 두 번째 "전환"을 넣어야합니다.

Apple의 Animation Types & Timing Programming Guide을보고 싶을 수도 있습니다.

5

Matt는 지적했듯이 시작 시간이 다른 동일한 레이어에 대해 서로 다른 애니메이션으로 구성된 애니메이션 그룹을 만들 수 있습니다. 또한 독립형 CAAnimation 개체 또는 CAAnimation 그룹에 대한 대리자를 설정하고 각각의 애니메이션이 완료로는 그룹의 일부 애니메이션이 자신의 대리인의 animationDidStop:finished: 메소드를 호출하지 않습니다 (AN animationDidStop:finished: 대리자 메서드를 호출합니다.

CAAnimation animationDidStop:finished: 메서드를 더 강력하게 사용하는 멋진 트릭을 알아 냈습니다. setValue:forKey: 메서드를 사용하여 독립 실행 형 애니메이션이나 애니메이션 그룹에 @ "animationCompletionBlock"키를 사용하여 코드 블록을 추가 한 다음 일반 메서드를 호출하여 @ "animationCompletionBlock"키에 대해 완료된 애니메이션을 확인하고 발견 된 경우 해당 블록을 실행합니다.

그 기술의 작동 예를 들어 GitHub의에이 프로젝트를 살펴 보자 :

CAAnimation demo with completion blocks

당신이 제안 당신은 또한,

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

블록 내부 애니메이션의 그룹을 설정합니다. 이렇게하면 CATransaction 클래스 메서드 setCompletionBlock:을 사용하여 현재 트랜잭션 그룹의 모든 애니메이션이 완료되면 코드 블록을 호출 할 수 있습니다. 한 트랜잭션에 대한 완료 블록은 다음 트랜잭션을 트리거 할 수 있습니다.난 항상 각 애니메이션의 시작 시간과 종료 시간을 설정하는 선호 무엇

0

는 별도로 이것이다 :

내가 (_ < 왜 <을 알고 개발 이제 BlocksKit -Repo에서 어떤 일이 일어나고,) A2DynamicDelegate를 사용하는 CAAnimation의 Category에 completionBlock 속성을 구현합니다.

은 다음과 같이 물건을 나를 수있게 :

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

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

훨씬 더 유연 :)

나는 완료 핸들러 here 내 코드를 업로드 한

. 헤더 파일의 고지를 살펴보십시오. 나는 그 방법이 왜 호출되지 않는 지 혼란 스럽다.

-1

내 "툴체인"까지 모든 "속임수"를 포함하지 않고,이 예 .. 직접하여 붙여 넣을 복사/...하지만 "체인"애니메이션을위한 정말 쉬운 전략을 보여 않습니다

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]; 
관련 문제