前回のコードを改良して、画面手前からフェードインするようなアニメーションを実装してみる。その逆に画面手前へフェードアウトさせる。そう、Dashboardのような動き。
サンプル実行
まずは動作から。こんな感じ。
画面手前から現れたように拡大で始まる
徐々に縮小して目の前に現れる
最後は実寸大(100x75)表示
実装
前回の処理でアニメーションを行っていた箇所をメソッドとして切り出す。
#define DURATION 0.5 - (void)animateFadeInOut:(BOOL)flag { CGFloat zPositionFrom = flag ? -1000 : 0; CGFloat zPositionTo = flag ? 0 : -1000; CGFloat opacityFrom = flag ? 0.25 : 1.0; CGFloat opacityTo = flag ? 1.0 : 0.25; CALayer* baseLayer = [self.view.layer.sublayers objectAtIndex:1]; CABasicAnimation *animation; animation=[CABasicAnimation animationWithKeyPath:@"zPosition"]; animation.fromValue=[NSNumber numberWithFloat:zPositionFrom]; animation.toValue=[NSNumber numberWithFloat:zPositionTo]; animation.duration=DURATION; animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault]; animation.repeatCount = 1; animation.delegate = self; [baseLayer addAnimation:animation forKey:@"zPosition"]; animation=[CABasicAnimation animationWithKeyPath:@"opacity"]; animation.fromValue=[NSNumber numberWithFloat:opacityFrom]; animation.toValue=[NSNumber numberWithFloat:opacityTo]; animation.duration=DURATION; animation.repeatCount = 1; animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault]; [baseLayer addAnimation:animation forKey:@"opacity"]; }フェードイン/フェードアウトによって値を逆転させている。フェードインの場合は zPosition -1000=>0, opacity 1.0=>0.25。zPositionが負値なので画面の手前から入ってくるような視覚効果となる。最後の 0 は原寸大の位置。フェードアウトの場合はちょうどその逆となる。
CAAnimation - デリゲート
CAAnimation にデリゲートを指定すると、アニメーションの開始と終了のタイミングで下記のメソッドが呼び出される。
- (void)animationDidStart:(CAAnimation *)theAnimation; - (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag
今回はアニメーション終了時にフェートアウトの場合はベースレイヤーを隠している(hidden=YES)。ただこの場合一瞬原寸大で表示されてしまう。アニメーション終了後はアニメーション開始直前の状態に戻っていることがわかる。この一瞬の表示を隠すにはどうしたらよいものか。removedOnCompletion = NO としても駄目だった。
なお delegateプロパティは retain属性が付いている。
CAAnimation Class Reference より転載。
Important: The delegate object is retained by the receiver. This is a rare exception to the memory management rules described in Memory Management Programming Guide.
An instance of CAAnimation should not be set as a delegate of itself. Doing so (outside of a garbage-collected environment) will cause retain cycles.
CAAnimation - タイミング関数
アニメーションのタイミング(速度の緩急)は標準で数種類用意されている。
CAMediaTimingFunction Class Reference より転載
Predefined Timing FunctionsLinearは速度一定。EaseIn とは最初遅めで徐々に早くなる。EaseOut はその逆で最初早めで徐々に遅くなる。EaseInEaseOut は最初が遅めで徐々に加速、その後減速して最後は遅くなる。Defaultは Bézier timing function でパラメータが (0.25,0.1), (0.25,0.1) のケース。なお Default は Mac OS X は 10.6 から利用可能。
These constants are used to specify one of the predefined timing functions used by functionWithName:.
NSString * const kCAMediaTimingFunctionLinear;
NSString * const kCAMediaTimingFunctionEaseIn;
NSString * const kCAMediaTimingFunctionEaseOut;
NSString * const kCAMediaTimingFunctionEaseInEaseOut;
NSString * const kCAMediaTimingFunctionDefault;
これらは +[CAMediaTimingFunction functionWithName:] でインスタンスを取得することができる。これを CAAnimation.timingFunctionへセットしてやればよい。
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionDefault];
Durationを短くする(0.25〜0.5秒)予定だが、その場合の視覚的効果はあまり差は感じられない。
[参考情報] CAMediaTimingFunction Class Reference
ソースコード
GitHub からどうぞ。
CoreAnimation3DSample2 at 2010-11-03 from xcatsan's iOS-Sample-Code - GitHub
Responses
Leave a Response