2014/01/17

アニメーションライブラリCanvasの仕組みを調べてみた

Xcodeでストーリーボードを編集するだけでアニメーションを可能にするライブラリCanvasを試す」で紹介したライブラリCanvasの仕組みがどうなっているのか気になったので調べてみました。

まずは、Custom Classに指定しているCSAnimationViewのヘッダファイルCSAnimationView.hを見てみます。

@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で指定できるようになるんですね。

CSAnimationTypeCAAnimation.hによると、文字列なので問題なし。

typedef NSString *CSAnimationType;

static CSAnimationType CSAnimationTypeBounceLeft   = @"bounceLeft";

続いて、実装を見ましょう (CSAnimationView.m)。

@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

CSAnimationclassForAnimationType:で文字列からクラスに変換し、そのクラスがperformAnimationOnViewすることでアニメーションしています。

では、そのアニメーションサブクラスのひとつであるCSBounceLeftのインタフェースと実装を見てみましょう。

@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(300, 0);
    [UIView animateKeyframesWithDuration:duration/4 delay:delay options:0 animations:^{
        // End
        view.transform = CGAffineTransformMakeTranslation(-10, 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:はアニメーション実行コードです。

@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 件のコメント:

コメントを投稿

注: コメントを投稿できるのは、このブログのメンバーだけです。