Core Animationの話 Part.1
-
Upload
yuichi-fujishige -
Category
Technology
-
view
1.564 -
download
6
description
Transcript of Core Animationの話 Part.1
Core Animation•矩形の高速表示+アニメーションのための仕組み (Open GL のラッパー)
• OS X v10.5で導入
• iOSでは最初からある
• CALayer/CAAnimation
• 2.5Dアニメーション (平面を3D配置)
•繰り返しアニメーション
•キーフレームアニメーション
• CAReplicatorLayer, CAEmitterLayer, CAGradientLayer, AVPlayerLayer, AVCaptureVideoPreviewLayer etc..
• NSViewとCALayerはあまりうまく統合されていない
• layer-backed mode
• layer-hosting mode
NSViewとの統合
NSView- (void)setWantsLayer:(BOOL)flag
• UIViewはCALayerのラッパー
• UIViewとCALayerは完全に統合されている(片方のプロパティを変えると相互に反映される ※若干名前違い有り)
UIViewとの統合
UIView@property(nonatomic, readonly, retain) CALayer *layer
#import <QuartzCore/QuartzCore.h>
UIView *view;...
CALayer *layer = [CALayer layer];...
[view.layer addSublayer:layer];
本題・よくある問題• 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"];
よく見かける解決策
•微妙に気持ち悪い
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"];
animatable• CALayerのプロパティのうち、アニメーション可能な物はドキュメントに
“animatable”の記載がある
position
Specifies the receiver’s position in the superlayer’s coordinate system. Animatable.
@property CGPoint position
暗黙的アニメーション• implicit animation
• animatableなプロパティを変更すると勝手にアニメーション発動
(hidden、addSubLayer, removeFromSuperLayer 等でも発動)
_testLayer.position = CGPointMake(x, y);
•暗黙的アニメーションは現在のトランザクション設定に基づいて発動する
•トランザクションを明示しない場合、デフォルトのトランザクションが適用される
[CATransaction begin];[CATransaction setAnimationDuration:2];
_testLayer.position = _endPoint;
[CATransaction commit];
CAAnimation• 明示的アニメーション(explicit animation)
• アニメーション=時間と共に変化するプロパティ
• CALayerにkey/valueで関連づける(明示的アニメーション)
• CALayerのプロパティを一時的に上書きする
• 細かい設定が可能
CABasicAnimation
CAPropertyAnimation
CAAnimation<CAMediaTiming, CAAction>
CAKeyframeAnimation
fromValue, toValue, byValue
keyPath
values, keyTimes
CABasicAnimation
duration=1.0keypath=“position”fromValue=(10,10)toValue= (20,20)
CALayer
CABasicAnimation
duration=1.0keypath=“opacity”
fromValue=0.0toValue=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で関連
CABasicAnimation
duration=1.0keypath=“position”fromValue=(10,10)toValue= (20,20)
CALayer
CABasicAnimation
duration=1.0keypath=“opacity”
fromValue=0.0toValue=1.0
key=”hoge”
key=”fuga”
LayerとAnimationはkey-valueで関連
layer->animationのkeyと、animationのkeypath は無関係
CALayeropacity=0.0
レイヤーツリー
CALayeropacity=0.0
opaticity=0.0 opaticity=0.0
Layer Tree Presentation Tree Render Tree (private)
layer.presentationLayer
レイヤーツリー
CALayeropacity=0.0
CABasicAnimation
duration=1.0keypath=“opacity”
fromValue=0.0toValue=1.0
opaticity=0.0 opaticity=0.0->1.0
Layer Tree Presentation Tree Render Tree (private)
layer.presentationLayer
opaticity=0.0->1.0
CAAction
•暗黙アニメーション発動時に実行されるアニメーション
CAAnimation : NSObject <CAAction>
CALayer- (id<CAAction>)actionForKey:(NSString *)event;
暗黙アニメーションとアクション
• Layerのプロパティ”X”を更新する
• [layer actionForKey:@”X”]で取り出されたAction(=Animation)が、Layerに追加される
• Layerのプロパティ値が実際に更新される
_testLayer.X = n;
CAAnimation<CAAction>CALayer
key=”X”
CALayeropacity=0.0
CALayeropacity=0.0
opaticity=0.0 opaticity=0.0
Layer Tree Presentation Tree Render Tree (private)
layer.presentationLayer
layer.opaticity=0の状態でlayer.opaticity=1を設定
CALayeropacity=1.0
CABasicAnimation
duration=1.0keypath=“opacity”
fromValue=0.0toValue=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”
CALayeropacity=1.0
CALayeropacity=1.0
opaticity=1.0 opaticity=1.0
Layer Tree Presentation Tree Render Tree (private)
layer.presentationLayer
layer.opaticity=0の状態でlayer.opaticity=1を設定
本題・よくある問題• 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"];
CALayeropacity=0.0
CALayeropacity=0.0
opaticity=0.0 opaticity=0.0
Layer Tree Presentation Tree Render Tree (private)
layer.presentationLayer
CALayeropacity=0.0
CABasicAnimation
duration=1.0keypath=“opacity”
fromValue=0.0toValue=1.0
opaticity=0.0 opaticity=0.0->1.0 opaticity=0.0->1.0
Layer Tree Presentation Tree Render Tree (private)
layer.presentationLayer
CALayeropacity=0.0
CALayeropacity=0.0
opaticity=0.0 opaticity=0.0
Layer Tree Presentation Tree Render Tree (private)
layer.presentationLayer
よく見る解決策•微妙に気持ち悪さが残る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"];
CALayeropacity=0.0
CALayeropacity=0.0
opaticity=0.0 opaticity=0.0
Layer Tree Presentation Tree Render Tree (private)
layer.presentationLayer
CALayeropacity=0.0
CABasicAnimation
duration=1.0keypath=“opacity”
fromValue=0.0toValue=1.0
opaticity=0.0 opaticity=0.0->1.0 opaticity=0.0->1.0
Layer Tree Presentation Tree Render Tree (private)
layer.presentationLayer
CALayeropacity=0.0
CABasicAnimation
duration=1.0keypath=“opacity”
fromValue=0.0toValue=1.0
opaticity=0.0 opaticity=1.0
Layer Tree Presentation Tree Render Tree (private)
layer.presentationLayer
opaticity=1.0
[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];
[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];
[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];
// 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しか無い
UIViewのLayer• UIView.layerは暗黙アニメーション(デフォルトアクション)が無効になっている
//[CATransaction begin]; // 不要//[CATransaction setDisableActions:YES]; // 不要view.layer.position = _endPoint;//[CATransaction commit]; // 不要[view.layer addAnimation:anim forKey:@"hoge"];