46
我所知道的 CoreAnimation Weizhong Yang a.k.a zonble [email protected] http://zonble.net Monday, March 28, 2011

Core Animation

Embed Size (px)

Citation preview

Page 1: Core Animation

我所知道的 CoreAnimation

Weizhong Yanga.k.a zonble

[email protected]://zonble.net

Monday, March 28, 2011

Page 2: Core Animation

今天用到的Sample Code

https://github.com/zonble/CAShowcase

New BSD License

Monday, March 28, 2011

Page 3: Core Animation

Why CoreAnimation?

• 這年頭動畫效果非常重要,尤其是 iPad

• 當 UIView 提供的動畫不夠用的時候,又還不需要用到自己寫 OpenGL,就該用 CoreAnimation 了。

Monday, March 28, 2011

Page 4: Core Animation

CoreAnimation 是?

• 一套 Mac/iOS framework

• 製作各種平面動畫• UIView 動畫其實算是 CoreAnimation 的

wrapper

Monday, March 28, 2011

Page 5: Core Animation

使用 CoreAnimation 的挑戰

• 要習慣 concurrent 的程式寫作

• 不過,反正做軟體最難的部份往往都不是程式…

Monday, March 28, 2011

Page 6: Core Animation

使用 CoreAnimation的挑戰

• 難的往往是設計與溝通• 在設計階段很難用 Mockup 溝通-怎麼講都很難讓對方理解最後會產生什麼動畫,除非把程式寫出來…

• 如果不是對方要的,那程式就白寫了…

Monday, March 28, 2011

Page 7: Core Animation

使用 CoreAnimation

• 都是 Objective-C 物件

• 可喜可賀

Monday, March 28, 2011

Page 8: Core Animation

重要的 Class

• CALayer:演員

• CAAnimation:腳本

• CATransaction:整體情境設定

Monday, March 28, 2011

Page 9: Core Animation

第一步

• #import <QuartzCore/QuartzCore.h>

Monday, March 28, 2011

Page 10: Core Animation

CALayer

Monday, March 28, 2011

Page 11: Core Animation

CALayer

• iOS

• 每個 UIView 都有一個 layer([aView layer] or aView.layer)

• Mac

• NSView 要特別設定 setWantsLayer:

• 今天以 iOS 為主

Monday, March 28, 2011

Page 12: Core Animation

CALayer 的 Interface 很像 View

• 有 frame、bounds、background color

• 把一個 layer 放到另外一個 layer 上面,是用 addSublayer

• 加入之後,也可以知道自己的 superlayer

Monday, March 28, 2011

Page 13: Core Animation

CALayer 也不像 View

• 不是 responder,不處理各種 event(Click、Touch…)

• 大部分 property 一改就會產生動畫

• 繪製內容的方法也稍微不一樣

Monday, March 28, 2011

Page 14: Core Animation

設定 CALayer

• CALayer *aLayer = [CALayer layer];

• aLayer.contents = (id)[UIImage imageNamed:@”test.jpg”].CGImage;

• 設定圖片內容時,其實就已經有 fade in/out 效果

Monday, March 28, 2011

Page 15: Core Animation

設定 CALayer

• aLayer.position = CGPointMake()...

• aLayer.bounds = CGRectMake()...

• 都會直接產生動畫效果• 預設動畫時間為 0.25 秒

Monday, March 28, 2011

Page 16: Core Animation

產生動畫的方法

• 直接改 Layer 的 property 就會有動畫

• 自己使用 CAAnimation 物件做動畫

• 後面再講…

Monday, March 28, 2011

Page 17: Core Animation

CATransaction 1

[CATransaction begin];

[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];

// 調整 CALayer

[CATransaction commit];

// 這樣會關閉各種動畫效果

Monday, March 28, 2011

Page 18: Core Animation

CATransaction 2[CATransaction begin];

[CATransaction setValue:[NSNumber numberWithFloat:2.0] forKey: kCATransactionAnimationDuration];

// 調整 CALayer

[CATransaction commit];

// 這樣會改變動畫時間

Monday, March 28, 2011

Page 19: Core Animation

先提一下 CATransition…

CATransition *t = [CATransition animation];

t.type = kCATransitionMoveIn

t.subtype = kCATransitionFromRight;

aLayer.contents = (id)[UIImage imageNamed:@”test.jpg”].CGImage;

[aLayer addAnimation:t forKey:@"Transition"];

// 產生移動效果

Monday, March 28, 2011

Page 20: Core Animation

CATransition

• 有很多 Private API(flip、cube)

• 用了會不會被 reject? 呃… 不知道。

Monday, March 28, 2011

Page 21: Core Animation

CAAnimation

Monday, March 28, 2011

Page 22: Core Animation

CAAnimation

• CABasicAnimation

• CAKeyframeAnimation

• CAAnimationGroup

• CATransition …前面講了

Monday, March 28, 2011

Page 23: Core Animation

CABasicAnimation

• [CABasicAnimation animationWithKeyPath:...]

• @”position”

• @”bounds”

• @”opacity”

• @”contents”...

Monday, March 28, 2011

Page 24: Core Animation

CABasicAnimation

• 還有• @”transform.rotation.x”

• @”transform.rotation.y”

• @”transform.rotation.z”

• ...

Monday, March 28, 2011

Page 25: Core Animation

CABasicAnimation

• fromValue = [NSValue...];

• toValue = [NSValue ...];

• duration = 3.0; //Seconds

• repeatCount = NSUIntegerMax; // Forever

Monday, March 28, 2011

Page 26: Core Animation

CAKeyframeAnimation

• 不是用 fromValue、toValue,而是用 CGPathRef

• CAKeyframeAnimation *a =[CAKeyframeAnimation animationWithKeyPath:@"position"];

• a.path = (CGPathRef)path;

Monday, March 28, 2011

Page 27: Core Animation

CAAnimationGroup

• CAAnimationGroup *group = [CAAnimationGroup animation];

• group.animations = [NSArray arrayWithObjects:anim1, anim2, nil];

Monday, March 28, 2011

Page 28: Core Animation

執行 CAAnimation

• [aLayer addAnimation:myAnimation forKey:@"MyKey"];

Monday, March 28, 2011

Page 29: Core Animation

fill mode

• 一個動畫結束,預設 layer 會跳回到動畫前的狀態

• animation.fillMode = kCAFillModeForwards;

• 這樣才會在結束的時候不動…

Monday, March 28, 2011

Page 30: Core Animation

另外要注意一下Property 的改變

CABasicAnimation *a = [CABasicAnimation animationWithKeyPath:@”bounds”];

a.fromValue = [NSValue valuwWithCGRect:fromRect];

a.toValue = [NSValue valuwWithCGRect:toRect];

[aLayer addAnimation:a forKey:@"boundsAnimation"];

NSLog(@”bounds:%@”, NSStringFromCGRect(aLayer.bounds));

• 還是會看到原本的 bounds,而不是動畫的 toValue 喔。

• 也就是說,在 layer 執行動畫的時候,去查看 layer 的 property,往往會跟你目前看到的不一樣。

Monday, March 28, 2011

Page 31: Core Animation

我的 Layer 要跑好幾段動畫,怎樣

一個動畫做完再做一個動畫

Monday, March 28, 2011

Page 32: Core Animation

一個動畫做完再做一個動畫

• [aLayer addAnimation:myAnimation1 forKey:@"MyKey1"];

• [aLayer addAnimation:myAnimation2 forKey:@"MyKey2"];

• 這兩個動畫會同時發生,不是一個跑完才跑下一個

Monday, March 28, 2011

Page 33: Core Animation

話說你要這樣寫也是可以啦…

• [self performSelector:@selector(runAnimation1) withObject:nil afterDelay:1.0]; // 一秒

• [self performSelector:@selector(runAnimation2) withObject:nil afterDelay:2.0]; // 二秒

• 很醜,完全不建議

Monday, March 28, 2011

Page 34: Core Animation

方法一:設定 beginTime

• animation1.beginTime = CACurrentMediaTime() + 1.0; // 一秒

• animation2.beginTime = CACurrentMediaTime() + 2.0; // 二秒

• 但有時候 CAAnimation 會被卡住,然後就被一起觸發,這樣不好…

Monday, March 28, 2011

Page 35: Core Animation

什麼時候 animation 會被卡住?

• layer 所在的 view 不在最上面

• 已經先寫了動畫,才去產生用來放置 layer 的 UIView,再把 layer 放進 view.layer 裡

• app 在背景

• runloop 有東西卡住

• 總之,真的很常發生

Monday, March 28, 2011

Page 36: Core Animation

方法二:用 delegate

animation.delegate = self;[myLayer addAnimation: animation forKey:@”key”];...- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag {// Fire another animation} // 這樣才會確實在第一個動畫結束時跑另一個動畫

Monday, March 28, 2011

Page 37: Core Animation

delegate 如何辨識是哪個 animation?…有點鳥蛋animation.delegate = self;animation.removedOnCompletion = NO;[myLayer addAnimation: animation forKey:@”key”];

...

- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag {if (theAnimation == [myLayer animationForKey:@”key”]) {

// Fire another animation [myLayer removeAllAnimations];

}}

// 目前還沒想到更好的辦法

Monday, March 28, 2011

Page 38: Core Animation

λ 抱怨 λ

• 一個 CAAnimation 結束的時候應該要有 block 可以跑啊啊啊啊啊啊啊…

• iOS 5 會有嗎?

• Lion 好像還沒看到

Monday, March 28, 2011

Page 39: Core Animation

一些撇步

Monday, March 28, 2011

Page 40: Core Animation

自動排列 CALayer?

• UILayer -layoutSublayers

• 我也常用 UIView -layoutSubviews 就是了…

Monday, March 28, 2011

Page 41: Core Animation

不設定 contents,而是在 CALayer 中用 Quartz 畫圖

- (void)drawInContext:(CGContextRef)ctx{ UIGraphicsPushContext(ctx);

// 把 ctx 變成 current graphics context 來用 :D UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:10.0]; CGContextSaveGState(ctx); CGContextAddPath(ctx, path.CGPath); CGContextClip(ctx); [image drawInRect:self.bounds]; CGContextRestoreGState(ctx); UIGraphicsPopContext();}

Monday, March 28, 2011

Page 42: Core Animation

透過某個 view 的 layer 取得這個 view 畫面

UIGraphicsBeginImageContext(self.bounds.size);CGContextRef ctx = UIGraphicsGetCurrentContext();[self.layer renderInContext:ctx];UIImage *anImage = UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext(); return anImage;

// 這個很好用 :D

Monday, March 28, 2011

Page 43: Core Animation

最後

Monday, March 28, 2011

Page 44: Core Animation

在 Mac 上面,不要在用到 Cocoa Drawing 的 NSView 中加上 CALayer,不要混用…

因為會慢到爆

Monday, March 28, 2011

Page 45: Core Animation

別忘了 Accessibility

• 讓視障朋友也可以順利使用 app

• 不過大部分人好像都不太注意…

• 一般的 UIView/UIControl 都支援 Accessibility,但是如果拿 CALayer 做成按鈕,需要自己實作 Accessibility 支援

• 不過今天也沒時間細說…

Monday, March 28, 2011

Page 46: Core Animation

完了Das ist alles.

Monday, March 28, 2011