「Xcodeでストーリーボードを編集するだけでアニメーションを可能にするライブラリCanvasを試す」で紹介したライブラリCanvasの仕組みがどうなっているのか気になったので調べてみました。
まずは、Custom Classに指定しているCSAnimationView
のヘッダファイルCSAnimationView.hを見てみます。
1 2 3 4 5 6 | @interface CSAnimationView : UIView @property ( nonatomic ) NSTimeInterval delay; @property ( nonatomic ) NSTimeInterval duration; @property ( nonatomic , copy ) CSAnimationType type; @property ( nonatomic ) BOOL pauseAnimationOnAwake; // If set, animation wont starts on awakeFromNib @end |
普通にプロパティを作っているだけでした。これだけで、User Defined Runtime Attributesで指定できるようになるんですね。
CSAnimationType
もCAAnimation.hによると、文字列なので問題なし。
1 2 3 | typedef NSString * CSAnimationType ; static CSAnimationType CSAnimationTypeBounceLeft = @"bounceLeft" ; |
続いて、実装を見ましょう (CSAnimationView.m)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | @implementation CSAnimationView - ( void )awakeFromNib { if ( self .type && self .duration && ! self .pauseAnimationOnAwake ) { [ self startCanvasAnimation ]; } } - ( void )startCanvasAnimation { Class <CSAnimation> class = [ CSAnimation classForAnimationType : self .type ]; [class performAnimationOnView : self duration : self .duration delay : self .delay ]; [ super startCanvasAnimation ]; } @end @implementation UIView (CSAnimationView) - ( void )startCanvasAnimation { [[ self subviews ] enumerateObjectsUsingBlock :^( id obj, NSUInteger idx, BOOL *stop) { [obj startCanvasAnimation ]; }]; } @end |
CSAnimation
のclassForAnimationType:
で文字列からクラスに変換し、そのクラスがperformAnimationOnView
することでアニメーションしています。
では、そのアニメーションサブクラスのひとつであるCSBounceLeft
のインタフェースと実装を見てみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | @interface CSBounceLeft : CSAnimation @end @implementation CSBounceLeft + ( void )load { [ self registerClass : self forAnimationType :CSAnimationTypeBounceLeft]; } + ( void )performAnimationOnView:( UIView *)view duration :(NSTimeInterval)duration delay :(NSTimeInterval)delay { // Start view .transform = CGAffineTransformMakeTranslation( 3 0 0 , 0 ); [ UIView animateKeyframesWithDuration :duration/ 4 delay :delay options : 0 animations :^{ // End view .transform = CGAffineTransformMakeTranslation(- 1 0 , 0 ); } completion :^( BOOL finished) { [ UIView animateKeyframesWithDuration :duration/ 4 delay : 0 options : 0 animations :^{ // End view .transform = CGAffineTransformMakeTranslation( 5 , 0 ); } completion :^( BOOL finished) { [ UIView animateKeyframesWithDuration :duration/ 4 delay : 0 options : 0 animations :^{ // End view .transform = CGAffineTransformMakeTranslation(- 2 , 0 ); } completion :^( BOOL finished) { [ UIView animateKeyframesWithDuration :duration/ 4 delay : 0 options : 0 animations :^{ // End view .transform = CGAffineTransformMakeTranslation( 0 , 0 ); } completion :^( BOOL finished) { }]; }]; }]; }]; } @end |
インタフェースは空で、実装はクラスメソッドが2つあるだけです。
+performAnimationOnView:duration:delay:
はアニメーション実行コードです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | @implementation CSAnimation static NSMutableDictionary *_animationClasses; + ( void )load { _animationClasses = [[ NSMutableDictionary alloc ] init ]; } + ( void )registerClass:(Class)class forAnimationType :(CSAnimationType)animationType { [_animationClasses setObject :class forKey :animationType]; } + (Class)classForAnimationType:(CSAnimationType)animationType { return [_animationClasses objectForKey :animationType]; } @end |
CSAnimationView
で使われていたclassForAnimationType:
もありますね。
このクラスでは、文字列→クラスの解決と、そのための辞書への登録の口があるだけでした。
そして、この辞書への要素追加は、各アニメーションサブクラスの+load
で行うようになっていることがわかります。
おわりに
ライブラリCanvasの内部を紹介しました。
非常にシンプルなので拡張も非常にしやすそうですね。
0 件のコメント:
コメントを投稿
注: コメントを投稿できるのは、このブログのメンバーだけです。