職人が教える!iOSアプリ開発で使いこなしたいとっておきのOSS

第1回様々なアニメーションを実現するiOSアプリ用トゥイーンライブラリ3種を比較!

はじめに

iOS SDK登場から早4年近くが経ち、使い回しの効くUIコンポーネントや、煩雑な手順を楽にするスクリプト、自作するには難易度の高い技術をライブラリ化したものなどなど、今では多くの便利なオープンソースソフトウェアが公開されています。

本連載ではそんなオープンソースソフトウェアの中で、有用かつあまり日本語での情報が少ないものを中心にご紹介していく予定です。具体的な使用方法や、ソースの内容にも踏み込んで解説していきますので、ぜひ皆様の日々の開発にお役に立ていただければ幸いです。

トゥイーンライブラリを使用するメリット

UIViewのアニメーションで指定できるイージングの種類は、

  • UIViewAnimationOptionCurveEaseInOut
  • UIViewAnimationOptionCurveEaseIn
  • UIViewAnimationOptionCurveEaseOut
  • UIViewAnimationOptionCurveLinear

の4種類しかなく、⁠ちょっときつめのイージングをかけたい」といったことを実現しようとすると、

  • 自分でそのイージングカーブの数式を定義し、その数式に従ってアニメーションさせたい値を時間経過に応じて変化させる処理を書く
  • CAAnimationクラスのtimingFunctionプロパティにカスタムのベジェ曲線を指定する
  • パラメータを変えたアニメーションを連続で実行して、それっぽい動きに仕立てる

といった手段をとる必要があり、一気に敷居が高くなってしまいます。

トゥイーンライブラリはそういった処理をラップしてくれているもので、使用することでさまざまなイージングカーブでのアニメーションを簡単に実現できるようになります。

今回はオープンソースのトゥイーンライブラリを3種紹介し、それぞれの使い方と、内部でどのような処理が行われているか、長所・短所について述べてみたいと思います。

なお、いずれのライブラリも⁠Robert Penner’s Easing Equations⁠に基づいており、"easeOutBounce"や"easeOutElastic"といった、ActionScriptのTweenerなどのトゥイーンライブラリでおなじみのイージングタイプの指定が可能となっています。

サンプルプロジェクトを以下のURLよりダウンロードしていただけます。動作やコードの確認にご利用ください。

PRTween

特徴

UIView や CALayer のプロパティを変化させるアニメーションだけでなく、数式に従って時間経過に応じて変化させた値を出力することもできるので、UIView や CALayer の標準アニメーション機能では指定できないプロパティをアニメーションさせたりといった応用も可能となります。

また CGFloat 型の値の変化だけではなく、CGPoint や CGRect 型にも対応していたり、終了時の処理を Blocks で記述できたりと、今回紹介する中では最も完成度が高いと思われます。

なお、ライセンスはBSDとなっています。

使い方

  1. ソースコードを以下のURLよりダウンロード

  2. libフォルダ(4つのファイルが入っています)ごとプロジェクトに追加

  3. PRTween.h をインポート

    • #import "PRTween.h"

  4. アニメーション開始処理を実装

    PRTweenPeriod インスタンスを生成します。

    引数にはトゥイーンさせる値の最初の値、最後の値、トゥイーンにかける時間を指定します。

    PRTweenPeriod *period = [PRTweenPeriod periodWithStartValue:kFromCenterPos.x endValue:kToCenterPos.x duration:1.0];

    PRTweenのaddTweenPeriod:target:selector:timingFunction: メソッドをコールします。

    selector には毎フレーム実行する処理を実装したメソッドを指定し、timingFunction に所望のイージングタイプを指定します。

    self.activeTweenOperation = [[PRTween sharedInstance] addTweenPeriod:period
                                                                  target:self
                                                                selector:@selector(update:)
                                                          timingFunction:&PRTweenTimingFunctionBounceOut];
  5. 毎フレーム実行する処理を実装

    period の tweenedValue プロパティには、イージングタイプと経過時間に従って出力された値が入っています。下記サンプルでは、その値に従って animateView の中心点の x座標を変化させています。

    - (void)update:(PRTweenPeriod*)period
    {
        [self.animateView setCenter:CGPointMake(period.tweenedValue, kToCenterPos.y)];
    }

補足

PRTweenには

+ (PRTweenOperation *)tween:(id)object property:(NSString*)property from:(CGFloat)from to:(CGFloat)to duration:(CGFloat)duration timingFunction:(PRTweenTimingFunction)timingFunction target:(NSObject*)target completeSelector:(SEL)selector;
+ (PRTweenOperation *)tween:(id)object property:(NSString*)property from:(CGFloat)from to:(CGFloat)to duration:(CGFloat)duration;

といった、UIViewやCALayerを引数に指定してアニメーションさせるメソッドもあり、前述した addTweenPeriod:target:selector:timingFunction: を使用する方法よりこっちの方が一見シンプルで使いやすいように思うのですが、実はあまり使い勝手がよくありません。

たとえば、引数のtimingFunctionに

PRTweenTimingFunctionCADefault
PRTweenTimingFunctionCAEaseIn
PRTweenTimingFunctionCAEaseOut
PRTweenTimingFunctionCAEaseInOut
PRTweenTimingFunctionCALinear
PRTweenTimingFunctionUIViewEaseIn
PRTweenTimingFunctionUIViewEaseOut
PRTweenTimingFunctionUIViewEaseInOut
PRTweenTimingFunctionUIViewLinear
NULL

これら以外の値を指定した場合、内部で処理がスキップされ、アニメーションが開始されません。つまり、冒頭でトゥイーンライブラリを利用するメリットとして挙げた「UIViewやCALayerで用意されていないカスタムイージングカーブを利用できる」といったメリットが享受できない、ということになります。

また、詳述はしませんが、property引数の指定にもクセがあったりします。

というわけでやや手順は増えるものの応用のきくaddTweenPeriod:target:selector:timingFunction:を利用する方法を紹介しました。

ShinobiTweener

特徴

UIViewやCALayerを実際にアニメーションさせる部分はライブラリに含んでおらず、数式に従って時間経過に応じて変化する値を出力することに特化したライブラリです。

このためUIKitにもQuartzCoreにも依存しておらず独立性は高いのですが、利用にあたって自分で書かなければならないコード量が多いというデメリットがあります。

使い方

  1. ソースコードを以下のURLよりダウンロード

  2. ShinobiTweenerフォルダごとプロジェクトに追加

  3. ShinobiTweener.h をインポート

    • #import "ShinobiTweener.h"

  4. 終了フラグと、トゥイーンさせる値を入れるためのメンバ変数を定義

    @interface ViewController ()
    {
        BOOL isShinobiTweenFinished;
        CGFloat shinobiValue;
    }
    @end

  5. アニメーション開始処理を実装

    // 終了フラグを初期化
    isShinobiTweenFinished = NO;
    
    // ループ開始
    [self tweenLoop];
    
    // トゥイーン処理開始
    [[ShinobiTweener sharedTweener] addTweenToFloat:&shinobiValue
                                             finish:kToCenterPos.x
                                       timeDuration:1.0
                                         transition:TWEENER_TRANSITION_BOUNCE_EASE_OUT
                                         onComplete:@selector(tweenFinish)
                                          forObject:self];
  6. 毎フレーム実行する処理を実装

    - (void)tweenUpdate
    {
        if(!isShinobiTweenFinished)
        {
            [[ShinobiTweener sharedTweener] update];
            [self.animateView setCenter:CGPointMake(shinobiValue, kToCenterPos.y)];
            
            [self tweenLoop];
        }
    }
    
    - (void)tweenLoop
    {
        [NSTimer scheduledTimerWithTimeInterval:(1.0f / 30.0f)
                                         target:self
                                       selector:@selector(tweenUpdate)
                                       userInfo:nil
                                        repeats:NO];
    }
  7. アニメーション終了処理を実装

    終了フラグにYESをセットします。

    - (void)tweenFinish
    {
        isShinobiTweenFinished = YES;
    }

TweenC

特徴

メソッド1つでアニメーションを実行でき、今回紹介する中では最も扱いやすいAPIとなっています。

ただ、致命的な欠点として、挙動が怪しいところがあります。今回のサンプルコードは、UIViewのx座標をアニメーションさせるだけの非常にシンプルなものですが、正常に動作しなかったため1ヵ所ライブラリのコードを修正して用いています(修正箇所はUPDというコメントで囲んであります⁠⁠。

また静的アナライザを走らせるとメモリリークの警告がたくさん出るとか、2009年以降、つまり、iOS 3.Xのころから更新が止まっているとか、諸々欠点があるため正直なところあまり利用はお勧めできません。

ただあえてここで紹介したいと思った理由は、CAKeyframeAnimationのvaluesプロパティを使用してカスタムイージングカーブでのアニメーションを実現している点です。

この方法は、AppleのキュメントAnimation Types and Timing Programming Guideでさらっと触れられてはいますが、実際のサンプルコードは載っていないため、このTweenCのコードがサンプルとしてとても参考になります。

具体的には、CAKeyframeAnimationのサブクラスである TweenAnimation に実装されているメソッド

-(void)calculatePositionForObject:(NSObject *)tweenObject start:(double)startPos change:(double)changePos duration:(double)duration;
-(void)calculateDegreesForObject:(NSObject *)tweenObject start:(double)startPos change:(double)changePos duration:(double)duration;
-(void)calculateScaleForObject:(NSObject *)tweenObject start:(double)startPos change:(double)changePos duration:(double)duration;
-(void)calculateOpacityForObject:(NSObject *)tweenObject start:(double)startPos change:(double)changePos duration:(double)duration;

これらの中で、⁠Robert Penner's Easing Equations⁠に基づいて算出された値の配列を生成し、values プロパティにセットしています。CAKeyframeAnimation でカスタムイージングカーブによるアニメーションを実装する際にはぜひ参考にしてみてください。

ライセンスはApache License 2.0です。

使い方

  1. ソースコードを以下のURLよりダウンロード

  2. 下記の6つのファイルをプロジェクトに追加

    • TweenC.h, TweenC.m, TweenConstants.h, TweenConstants.m, TweenerAnimation.h, TweenerAnimation.m
  3. TweenC.h をインポート

    • #import "TweenC.h"

  4. アニメーション開始処理を実装

    [TweenC animateView:self.animateView 
          withAnimation:kTweenEaseOutBounce
            andDuration:1.0
                toPoint:kToOriginPos
               delegate:self];

まとめ

さまざまなタイプのイージングカーブでのアニメーションを実現する、トゥイーンライブラリを3種紹介しました。この中での筆者のオススメはPRTweenですが、他2つもカスタムイージングカーブをどう実現しているかの観点でソースを見てみると参考になるので、ぜひ一度お試しください!

おすすめ記事

記事・ニュース一覧