Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Core Animationの話 Part.1
初めによくある問題
2012.05.19
ふじしげ ゆういち
@nakiwo
• ふじしげ ゆういち
• @nakiwo
• 株式会社フィードテイラー
http://feedtailor.jp/
Book+
そら案内
SYNCNEL
• ふじしげ ゆういち
• @nakiwo
• http://www.nakiwo.com/
洞窟物語
めがね
(Mac AppStore)
今日のテーマ
•Core Animation
•最初にはまりがちな問題
『アニメーション終了後表示が戻る』
•結論は簡単。過程が複雑
•iOS
今日のサンプル
https://github.com/nakiwo/CoreAnimationSample1
Core Animation
•矩形の高速表示+アニメーションのため
の仕組み (Open GL のラッパー)
•OS X v10.5で導入
•iOSでは最初からある
•CALayer/CAAnimation
何が嬉しい?
• Core Animationでしかできない事がある
• UIView/NSViewのアニメーション機構で
済むならそれが一番楽
•2.5Dアニメーション (平面を3D配置)
•繰り返しアニメーション
•キーフレームアニメーション
• CAReplicatorLayer, CAEmitterLayer,
CAGradientLayer, AVPlayerLayer,
AV...
•NSViewとCALayerはあまりうまく統
合されていない
•layer-backed mode
•layer-hosting mode
NSViewとの統合
NSView
- (void)setWantsLayer:(BOOL)flag
•UIViewはCALayerのラッパー
•UIViewとCALayerは完全に統合されて
いる(片方のプロパティを変えると相互
に反映される ※若干名前違い有り)
UIViewとの統合
UIView
@property(nonatomic, ...
#import <QuartzCore/QuartzCore.h>
UIView *view;
...
CALayer *layer = [CALayer layer];
...
[view.layer addSublayer:layer];
本題・よくある問題
•CABasicAnimationをLayerに追加す
るとアニメーションした後元の表示に
戻る
CABasicAnimation *anim =
[CABasicAnimation animationWithKeyPath...
デモ
※ Keynoteを中断する時は[H]を押す
よく見かける解決策
•微妙に気持ち悪い
CABasicAnimation *anim = [CABasicAnimation
animationWithKeyPath:@"position"];
anim.fromValue = [NSValu...
何が問題?
CALayer
•Core Animationレンダリングシステム
が表示する内容を表すデータモデル
•NSView/UIViewと違い、イベントハン
ドリングの仕組みを持っていない
(表示専任)
animatable
•CALayerのプロパティのうち、アニ
メーション可能な物はドキュメントに
animatable の記載がある
position
Specifies the receiver’s position in the
supe...
暗黙的アニメーション
•implicit animation
•animatableなプロパティを変更すると
勝手にアニメーション発動
(hidden、addSubLayer,
removeFromSuperLayer 等でも発動)
_test...
•暗黙的アニメーションは現在のトラン
ザクション設定に基づいて発動する
•トランザクションを明示しない場合、
デフォルトのトランザクションが適用
される
[CATransaction begin];
[CATransaction setAnim...
CAAnimation
• 明示的アニメーション(explicit animation)
• アニメーション=時間と共に変化するプロパ
ティ
• CALayerにkey/valueで関連づける
(明示的アニメーション)
• CALayerのプロ...
CABasicAnimation
CAPropertyAnimation
CAAnimation
<CAMediaTiming, CAAction>
CAKeyframeAnimation
fromValue, toValue, byValue...
CABasicAnimation
duration=1.0
keypath=“position”
fromValue=(10,10)
toValue= (20,20)
CALayer
CABasicAnimation
duration=1.0
...
CABasicAnimation
duration=1.0
keypath=“position”
fromValue=(10,10)
toValue= (20,20)
CALayer
CABasicAnimation
duration=1.0
...
CALayer
opacity=0.0
レイヤーツリー
CALayer
opacity=0.0
opaticity=0.0 opaticity=0.0
Layer Tree Presentation Tree Render Tree (priv...
レイヤーツリー
CALayer
opacity=0.0
CABasicAnimation
duration=1.0
keypath=“opacity”
fromValue=0.0
toValue=1.0
opaticity=0.0 opatic...
CAAction
•暗黙アニメーション発動時に実行され
るアニメーション
CAAnimation : NSObject <CAAction>
CALayer
- (id<CAAction>)actionForKey:(NSString *)ev...
暗黙アニメーションとアクション
• Layerのプロパティ X を更新する
• [layer actionForKey:@ X ]で取り出された
Action(=Animation)が、Layerに追加され
る
• Layerのプロパティ値が実...
CALayer
opacity=0.0
CALayer
opacity=0.0
opaticity=0.0 opaticity=0.0
Layer Tree Presentation Tree Render Tree (private)
lay...
CALayer
opacity=1.0
CABasicAnimation
duration=1.0
keypath=“opacity”
fromValue=0.0
toValue=1.0
opaticity=1.0 opaticity=0.0-...
CALayer
opacity=1.0
CALayer
opacity=1.0
opaticity=1.0 opaticity=1.0
Layer Tree Presentation Tree Render Tree (private)
lay...
本題・よくある問題
•CABasicAnimationをLayerに追加す
るとアニメーションした後元の表示に
戻る
CABasicAnimation *anim =
[CABasicAnimation animationWithKeyPath...
CALayer
opacity=0.0
CALayer
opacity=0.0
opaticity=0.0 opaticity=0.0
Layer Tree Presentation Tree Render Tree (private)
lay...
CALayer
opacity=0.0
CABasicAnimation
duration=1.0
keypath=“opacity”
fromValue=0.0
toValue=1.0
opaticity=0.0 opaticity=0.0-...
CALayer
opacity=0.0
CALayer
opacity=0.0
opaticity=0.0 opaticity=0.0
Layer Tree Presentation Tree Render Tree (private)
lay...
よく見る解決策
•微妙に気持ち悪さが残る
CABasicAnimation *anim = [CABasicAnimation
animationWithKeyPath:@"position"];
anim.fromValue = [NSVal...
CALayer
opacity=0.0
CALayer
opacity=0.0
opaticity=0.0 opaticity=0.0
Layer Tree Presentation Tree Render Tree (private)
lay...
CALayer
opacity=0.0
CABasicAnimation
duration=1.0
keypath=“opacity”
fromValue=0.0
toValue=1.0
opaticity=0.0 opaticity=0.0-...
CALayer
opacity=0.0
CABasicAnimation
duration=1.0
keypath=“opacity”
fromValue=0.0
toValue=1.0
opaticity=0.0 opaticity=1.0
...
解決策
•先にLayerの値を更新しておく
[CATransaction begin]; // 暗黙トランザクションのdurationを長めに設定(確認用)
[CATransaction setAnimationDuration:4];
// animations追加
CABasicAn...
[CATransaction begin]; // 暗黙トランザクションのdurationを長めに設定(確認用)
[CATransaction setAnimationDuration:4];
// animations追加
CABasicAn...
[CATransaction begin];
// 暗黙トランザクションのdurationを長めに設定(explicit3との対比確認のため)
[CATransaction setAnimationDuration:4];
NSLog(@"cu...
// animations追加
CABasicAnimation *anim = [CABasicAnimation
animationWithKeyPath:@"position"];
anim.fromValue = [NSValue va...
UIViewのLayer
•UIView.layerは暗黙アニメーション(デ
フォルトアクション)が無効になってい
る
//[CATransaction begin]; // 不要
//[CATransaction setDisableActi...
参考資料
• Core Animation Programming Guide
Core Animationの話  Part.1
Upcoming SlideShare
Loading in …5
×

Core Animationの話 Part.1

3,010 views

Published on

Core Animation でアニメーション終了後位置が戻る問題の話。

第44回 Cocoa勉強会関西の発表資料。

Published in: Technology

Core Animationの話 Part.1

  1. 1. Core Animationの話 Part.1 初めによくある問題 2012.05.19 ふじしげ ゆういち @nakiwo
  2. 2. • ふじしげ ゆういち • @nakiwo • 株式会社フィードテイラー http://feedtailor.jp/ Book+ そら案内 SYNCNEL
  3. 3. • ふじしげ ゆういち • @nakiwo • http://www.nakiwo.com/ 洞窟物語 めがね (Mac AppStore)
  4. 4. 今日のテーマ •Core Animation •最初にはまりがちな問題 『アニメーション終了後表示が戻る』 •結論は簡単。過程が複雑 •iOS
  5. 5. 今日のサンプル https://github.com/nakiwo/CoreAnimationSample1
  6. 6. Core Animation •矩形の高速表示+アニメーションのため の仕組み (Open GL のラッパー) •OS X v10.5で導入 •iOSでは最初からある •CALayer/CAAnimation
  7. 7. 何が嬉しい? • Core Animationでしかできない事がある • UIView/NSViewのアニメーション機構で 済むならそれが一番楽
  8. 8. •2.5Dアニメーション (平面を3D配置) •繰り返しアニメーション •キーフレームアニメーション • CAReplicatorLayer, CAEmitterLayer, CAGradientLayer, AVPlayerLayer, AVCaptureVideoPreviewLayer etc..
  9. 9. •NSViewとCALayerはあまりうまく統 合されていない •layer-backed mode •layer-hosting mode NSViewとの統合 NSView - (void)setWantsLayer:(BOOL)flag
  10. 10. •UIViewはCALayerのラッパー •UIViewとCALayerは完全に統合されて いる(片方のプロパティを変えると相互 に反映される ※若干名前違い有り) UIViewとの統合 UIView @property(nonatomic, readonly, retain) CALayer *layer
  11. 11. #import <QuartzCore/QuartzCore.h> UIView *view; ... CALayer *layer = [CALayer layer]; ... [view.layer addSublayer:layer];
  12. 12. 本題・よくある問題 •CABasicAnimationをLayerに追加す るとアニメーションした後元の表示に 戻る CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"position"]; anim.fromValue = [NSValue valueWithCGPoint:_startPoint]; anim.toValue = [NSValue valueWithCGPoint:_endPoint]; anim.duration = 0.5; anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; [_testLayer addAnimation:anim forKey:@"hoge"];
  13. 13. デモ ※ Keynoteを中断する時は[H]を押す
  14. 14. よく見かける解決策 •微妙に気持ち悪い CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"position"]; anim.fromValue = [NSValue valueWithCGPoint:_startPoint]; anim.toValue = [NSValue valueWithCGPoint:_endPoint]; anim.duration = 0.5; anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; // アニメーションが終了しても自動削除しない // 終了後はtoValueをキープ anim.removedOnCompletion = NO; anim.fillMode = kCAFillModeForwards; [_testLayer addAnimation:anim forKey:@"hoge"];
  15. 15. 何が問題?
  16. 16. CALayer •Core Animationレンダリングシステム が表示する内容を表すデータモデル •NSView/UIViewと違い、イベントハン ドリングの仕組みを持っていない (表示専任)
  17. 17. animatable •CALayerのプロパティのうち、アニ メーション可能な物はドキュメントに animatable の記載がある position Specifies the receiver’s position in the superlayer’s coordinate system. Animatable. @property CGPoint position
  18. 18. 暗黙的アニメーション •implicit animation •animatableなプロパティを変更すると 勝手にアニメーション発動 (hidden、addSubLayer, removeFromSuperLayer 等でも発動) _testLayer.position = CGPointMake(x, y);
  19. 19. •暗黙的アニメーションは現在のトラン ザクション設定に基づいて発動する •トランザクションを明示しない場合、 デフォルトのトランザクションが適用 される [CATransaction begin]; [CATransaction setAnimationDuration:2]; _testLayer.position = _endPoint; [CATransaction commit];
  20. 20. CAAnimation • 明示的アニメーション(explicit animation) • アニメーション=時間と共に変化するプロパ ティ • CALayerにkey/valueで関連づける (明示的アニメーション) • CALayerのプロパティを一時的に上書きする • 細かい設定が可能
  21. 21. CABasicAnimation CAPropertyAnimation CAAnimation <CAMediaTiming, CAAction> CAKeyframeAnimation fromValue, toValue, byValue keyPath values, keyTimes
  22. 22. CABasicAnimation duration=1.0 keypath=“position” fromValue=(10,10) toValue= (20,20) CALayer CABasicAnimation duration=1.0 keypath=“opacity” fromValue=0.0 toValue=1.0 - (void)addAnimation:(CAAnimation *)anim forKey:(NSString *)key; - (void)removeAnimationForKey:(NSString *)key; - (void)removeAllAnimations; - (NSArray *)animationKeys; - (CAAnimation *)animationForKey:(NSString *)key; key=”hoge” key=”fuga” LayerとAnimationはkey-valueで関連
  23. 23. CABasicAnimation duration=1.0 keypath=“position” fromValue=(10,10) toValue= (20,20) CALayer CABasicAnimation duration=1.0 keypath=“opacity” fromValue=0.0 toValue=1.0 key=”hoge” key=”fuga” LayerとAnimationはkey-valueで関連 layer->animationのkeyと、 animationのkeypath は無関係
  24. 24. CALayer opacity=0.0 レイヤーツリー CALayer opacity=0.0 opaticity=0.0 opaticity=0.0 Layer Tree Presentation Tree Render Tree (private) layer.presentationLayer
  25. 25. レイヤーツリー CALayer opacity=0.0 CABasicAnimation duration=1.0 keypath=“opacity” fromValue=0.0 toValue=1.0 opaticity=0.0 opaticity=0.0->1.0 Layer Tree Presentation Tree Render Tree (private) layer.presentationLayer opaticity=0.0->1.0
  26. 26. CAAction •暗黙アニメーション発動時に実行され るアニメーション CAAnimation : NSObject <CAAction> CALayer - (id<CAAction>)actionForKey:(NSString *)event;
  27. 27. 暗黙アニメーションとアクション • Layerのプロパティ X を更新する • [layer actionForKey:@ X ]で取り出された Action(=Animation)が、Layerに追加され る • Layerのプロパティ値が実際に更新される _testLayer.X = n; CAAnimation <CAAction> CALayer key=”X”
  28. 28. CALayer opacity=0.0 CALayer opacity=0.0 opaticity=0.0 opaticity=0.0 Layer Tree Presentation Tree Render Tree (private) layer.presentationLayer layer.opaticity=0の状態で layer.opaticity=1を設定
  29. 29. CALayer opacity=1.0 CABasicAnimation duration=1.0 keypath=“opacity” fromValue=0.0 toValue=1.0 opaticity=1.0 opaticity=0.0->1.0 opaticity=0.0->1.0 Layer Tree Presentation Tree Render Tree (private) layer.presentationLayer layer.opaticity=0の状態で layer.opaticity=1を設定 key= ”opacity”
  30. 30. CALayer opacity=1.0 CALayer opacity=1.0 opaticity=1.0 opaticity=1.0 Layer Tree Presentation Tree Render Tree (private) layer.presentationLayer layer.opaticity=0の状態で layer.opaticity=1を設定
  31. 31. 本題・よくある問題 •CABasicAnimationをLayerに追加す るとアニメーションした後元の表示に 戻る CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"position"]; anim.fromValue = [NSValue valueWithCGPoint:_startPoint]; anim.toValue = [NSValue valueWithCGPoint:_endPoint]; anim.duration = 0.5; anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; [_testLayer addAnimation:anim forKey:@"hoge"];
  32. 32. CALayer opacity=0.0 CALayer opacity=0.0 opaticity=0.0 opaticity=0.0 Layer Tree Presentation Tree Render Tree (private) layer.presentationLayer
  33. 33. CALayer opacity=0.0 CABasicAnimation duration=1.0 keypath=“opacity” fromValue=0.0 toValue=1.0 opaticity=0.0 opaticity=0.0->1.0 opaticity=0.0->1.0 Layer Tree Presentation Tree Render Tree (private) layer.presentationLayer
  34. 34. CALayer opacity=0.0 CALayer opacity=0.0 opaticity=0.0 opaticity=0.0 Layer Tree Presentation Tree Render Tree (private) layer.presentationLayer
  35. 35. よく見る解決策 •微妙に気持ち悪さが残る CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"position"]; anim.fromValue = [NSValue valueWithCGPoint:_startPoint]; anim.toValue = [NSValue valueWithCGPoint:_endPoint]; anim.duration = 0.5; anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; // アニメーションが終了しても自動削除しない // 終了後はtoValueをキープ anim.removedOnCompletion = NO; anim.fillMode = kCAFillModeForwards; [_testLayer addAnimation:anim forKey:@"hoge"];
  36. 36. CALayer opacity=0.0 CALayer opacity=0.0 opaticity=0.0 opaticity=0.0 Layer Tree Presentation Tree Render Tree (private) layer.presentationLayer
  37. 37. CALayer opacity=0.0 CABasicAnimation duration=1.0 keypath=“opacity” fromValue=0.0 toValue=1.0 opaticity=0.0 opaticity=0.0->1.0 opaticity=0.0->1.0 Layer Tree Presentation Tree Render Tree (private) layer.presentationLayer
  38. 38. CALayer opacity=0.0 CABasicAnimation duration=1.0 keypath=“opacity” fromValue=0.0 toValue=1.0 opaticity=0.0 opaticity=1.0 Layer Tree Presentation Tree Render Tree (private) layer.presentationLayer opaticity=1.0
  39. 39. 解決策 •先にLayerの値を更新しておく
  40. 40. [CATransaction begin]; // 暗黙トランザクションのdurationを長めに設定(確認用) [CATransaction setAnimationDuration:4]; // animations追加 CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"position"]; anim.fromValue = [NSValue valueWithCGPoint:_startPoint]; anim.toValue = [NSValue valueWithCGPoint:_endPoint]; anim.duration = 0.3; anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; // モデルの値も更新しておく // しかしこの方法だとimplicitアニメーションも同時に走ってしまう! // 同じkeyPathに対するアニメーションが2つ以上ある場合、どちらが勝つかは不定? // 登録された順番により結果が異なる様子 _testLayer.position = _endPoint; // ここで暗黙アニメーション発動 [self showAnimations]; // positionアニメーションが登録されている事がわかる [_testLayer addAnimation:anim forKey:@"hoge"]; // 適当な名前のキーで追加 [self showAnimations]; // hoge/positionの2アニメーションが登録されている事がわかる [CATransaction commit];
  41. 41. [CATransaction begin]; // 暗黙トランザクションのdurationを長めに設定(確認用) [CATransaction setAnimationDuration:4]; // animations追加 CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"position"]; anim.fromValue = [NSValue valueWithCGPoint:_startPoint]; anim.toValue = [NSValue valueWithCGPoint:_endPoint]; anim.duration = 0.3; anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; // モデルの値も更新しておく // しかしこの方法だとimplicitアニメーションも同時に走ってしまう! // 同じkeyPathに対するアニメーションが2つ以上ある場合、どちらが勝つかは不定? // 登録された順番により結果が異なる様子 _testLayer.position = _endPoint; // ここで暗黙アニメーション発動 [self showAnimations]; // positionアニメーションが登録されている事がわかる [_testLayer addAnimation:anim forKey:@"hoge"]; // 適当な名前のキーで追加 [self showAnimations]; // hoge/positionの2アニメーションが登録されている事がわかる [CATransaction commit];
  42. 42. [CATransaction begin]; // 暗黙トランザクションのdurationを長めに設定(explicit3との対比確認のため) [CATransaction setAnimationDuration:4]; NSLog(@"current transaction animationDuration : %f", [CATransaction animationDuration]); // animations追加 CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"position"]; anim.fromValue = [NSValue valueWithCGPoint:_startPoint]; anim.toValue = [NSValue valueWithCGPoint:_endPoint]; anim.duration = 1; anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; // おすすめ解決策その1 // モデルの値も更新しておく。 _testLayer.position = _endPoint; // デフォルトアクションが発動 [self showAnimations]; // positionのみ(デフォルトアクション) // アニメーションを登録する際、元のプロパティ名をキーとして使用する // 同じキーのアニメーションは1つしか登録出来ない。同じ名前があると上書きされる。 // implicitアニメーションのアニメーションと同じキーで上書き [_testLayer addAnimation:anim forKey:@"position"]; [self showAnimations]; // positionのみ(アプリが指定したインスタンス) [CATransaction commit];
  43. 43. // animations追加 CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"position"]; anim.fromValue = [NSValue valueWithCGPoint:_startPoint]; anim.toValue = [NSValue valueWithCGPoint:_endPoint]; anim.duration = 0.5; anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; // おすすめ解決策その2 // モデルの値も更新しておく // デフォルトアクション(=implicitアニメーション)が走らないように設定 [CATransaction begin]; [CATransaction setDisableActions:YES]; _testLayer.position = _endPoint; // Layerアクションが無効になっているのでアニメーションは発動しない [CATransaction commit]; [self showAnimations]; // アニメーション無し [_testLayer addAnimation:anim forKey:@"hoge"]; // 適当な名前のキーで追加 [self showAnimations]; // hogeしか無い
  44. 44. UIViewのLayer •UIView.layerは暗黙アニメーション(デ フォルトアクション)が無効になってい る //[CATransaction begin]; // 不要 //[CATransaction setDisableActions:YES]; // 不要 view.layer.position = _endPoint; //[CATransaction commit]; // 不要 [view.layer addAnimation:anim forKey:@"hoge"];
  45. 45. 参考資料 • Core Animation Programming Guide

×