2009-12-15 40 views
32

Cách nào là cách thanh lịch và mô-đun nhất để hoạt ảnh chuỗi trong ngữ cảnh Hoạt ảnh chính?Hoạt ảnh lõi Chaining Animation Animation

Ý tôi là để làm hình ảnh động mà bắt đầu chỉ khi khác thành (ví dụ, thay đổi position và sau đó opacity) .. Cách tiếp cận thông thường là để trực tiếp thay đổi thuộc tính:

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

nhưng điều này sẽ làm cho họ đồng thời gian. Tôi muốn chờ đợi người kia.

Và điều gì về chuỗi hoạt ảnh cho các đối tượng khác nhau? Tôi đã đọc về CATransaction sử dụng như:

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

nhưng nó dường như không làm việc ..

Trả lời

73

Bạn cũng có thể sử dụng nhóm hoạt ảnh và sử dụng trường beginTime của hoạt ảnh. Hãy thử một cái gì đó như thế này:

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]; 

Lưu ý rằng thời lượng của toàn bộ hoạt ảnh là 10 giây. Người đầu tiên bắt đầu từ giây thứ hai và người thứ hai bắt đầu sau 5 giây.

+9

lưu ý rằng điều này là rất tốt, nhưng sẽ chỉ làm việc cho hình ảnh động áp dụng cho một đơn lớp. – nielsbot

+0

Ngoài ra nếu bạn muốn gọi một phương thức ngay khi hoạt ảnh đầu tiên kết thúc, bạn không thể. animationDidStop chỉ được gọi khi toàn bộ nhóm kết thúc. – durazno

+0

đường dẫn chính '" vị trí "' là một 'CGPoint' cần được mã hóa với' NSValue' (không phải là 'NSNumber'). – wcochran

0

Tôi không tin bạn có thể "làm tổ" CA hình ảnh động là bạn có trong ví dụ của bạn.

Bạn cần chỉ định ủy quyền cho hoạt ảnh và đặt "chuyển tiếp" thứ hai của bạn trong bộ chọn animationDidStop:finished: của người được ủy quyền.

Có thể muốn xem qua số Animation Types & Timing Programming Guide của Apple.

5

Như Matt đã chỉ ra, bạn có thể tạo các nhóm hoạt ảnh bao gồm các hoạt ảnh khác nhau cho cùng một lớp với thời gian bắt đầu khác nhau. Bạn cũng có thể thiết lập một đại biểu cho độc lập CAAnimation đối tượng hoặc CAAnimation Groups và vì mỗi hình ảnh động kết thúc nó sẽ gọi một phương pháp animationDidStop:finished: đại biểu (lưu ý rằng hình ảnh động là một phần của một nhóm sẽ không gọi phương pháp đại biểu của họ animationDidStop:finished:.

Tôi đã tìm ra một mẹo hay để sử dụng phương thức CAAnimation animationDidStop:finished: mạnh mẽ hơn. Tôi sử dụng phương thức setValue:forKey: để thêm một khối mã vào nhóm hoạt ảnh hoặc hoạt ảnh độc lập, với khóa @ "animationCompletionBlock", sau đó viết tổng quát animationDidStop:finished: phương pháp kiểm tra hoạt ảnh vừa hoàn thành cho khóa @ "animationCompletionBlock" và nếu tìm thấy nó, hãy thực thi khối mã ở đó.

Hãy nhìn vào dự án này trên github cho một ví dụ làm việc của kỹ thuật mà:

CAAnimation demo with completion blocks

Bạn một cũng Đặt một nhóm các hình ảnh động bên trong một khối

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

, như bạn đề nghị. Khi thực hiện điều đó, bạn có thể sử dụng phương thức lớp CATransactionsetCompletionBlock: để gọi một khối mã khi tất cả hoạt ảnh trong nhóm giao dịch hiện tại hoàn tất. Khối hoàn thành cho một giao dịch sau đó có thể kích hoạt giao dịch tiếp theo.

0

Những gì tôi đã luôn luôn ưa thích để thiết lập bắt đầu và kết thúc thời gian của mỗi hình ảnh động riêng rẽ là thế này:

tôi đã sử dụng A2DynamicDelegate (có phát triển hiện nay đang xảy ra trong BlocksKit -Repo, ai biết tại sao < _ <) để thực hiện một thuộc tính completionBlock trong một Category on CAAnimation.

Điều này cho phép tôi làm những thứ như thế này:

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

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

nhiều linh hoạt :) hơn

Tôi đã tải lên mã của tôi để hoàn thành xử lý here. Tuy nhiên, hãy xem thông báo trong tệp tiêu đề. Tôi thực sự bối rối vì sao phương pháp này không được gọi.

-1

Nếu không bao gồm tất cả các "thủ thuật" lên "toolchain" của tôi, ví dụ này không phải là sao chép trực tiếp/thể dán ... nhưng nó cho thấy một chiến lược thực sự dễ dàng cho hình ảnh động "xiềng xích" ..

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. 

này rõ ràng là phụ thuộc vào một số "ma thuật bên ngoài", nhưng khái niệm này là đơn giản, và loại bỏ (thông qua các phụ thuộc) cần phải "đối phó với" bất kỳ loại nào của tổng phái đoàn. Cụ thể, các danh mục animate:from:to:time:easing:completion, v.v. đến từ tuyệt vời FunSize Framework, on Github.

0

tôi kéo này bằng cách sử dụng phương pháp setCompletionBlock để xác định một kết thúc mà gây nên các hình ảnh động tiếp theo khi người đầu tiên được hoàn thành:

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