アニメーションを行うには(AndroidMode:SDK編)

◆PROCESSING 逆引きリファレンス

 カテゴリー:スマホ(AndroidMode)

アニメーションを行うには(AndroidMode:SDK編)

【概要】

PROCESSINGにAndroidMode を導入する事で、PROCESSINGで開発したプログラムをAndroid端末上で動かす事ができるようになります。

AndroidModeの導入については「PROCESSINGをAndroid端末で動かすには(4.0版)」記事を参照してください。

アニメーションには、大きく2種類のものがあります。

1つは、画像そのものに対して行うアニメーション(画像を移動する、回転する、透明にするなど)で、Tweenアニメーションと呼ばれています。

もう1つは、異なる画像を高速に切り替えながら表示するアニメーション(いわゆるパラパラ漫画風アニメ)で、Frameアニメーションと呼ばれています。

(画像URL:illust-AC 様:nomoさん、愛楽ゆに の 創作研究所 様)

Android にはアニメーションを行う命令が沢山あります。

しかしその多くは、アニメーションする対象に View を想定しているため、PROCESSINGでは利用することができません(正確に言うと利用はできるのですが、いろいろと困難を伴います)。

ですが、あきらめるのは早いです。

数ある命令の中でProperty Animation は、View以外のオブジェクトに対してパラメータを線形変更できるため、PROCESSINGでも利用する事ができるのです。

Property Animationを使うと、PImageに対してTweenアニメーションを行わせることが可能となります。また、がんばれば Frameアニメーションも実現できます。

Property Animationには、Animatorクラスをベースとしたサブクラスが沢山ありますが、本記事ではAnimatorSetクラスとObjectAnimatorクラスを取り上げます。

これらのクラスをざっくりと説明すると

Animatorクラス
Property Animationの基本的なメソッドが定義されているスーパークラスです。実際には、このクラスを元に派生した下位のクラスを使います。

ValueAnimatorクラス
ある数値からある数値まで、指定した時間で変化する値を計算するクラスです。

ObjectAnimatorクラス
オブジェクト(Viewなど)がもつプロパティを、指定した時間で変化させるクラスです。

TimeAnimatorクラス
アニメーションフレームの更新通知を受け取って処理をすることができるクラスです。最小16ms単位でアニメーションフレームの更新通知を受け取ります。

AnimatorSetクラス
複数のアニメーションをまとめるクラスです。ValueAnimatorやObjectAnimatorクラスで定義した値の変化を、1つのアニメーションとしてまとめて再生する事が可能です。

詳しくは下記公式リファレンスを参照して下さい。

また、以下のページが大変参考となりました。ありがとうございます。

なおProperty AnimationはAndroidの命令ですので、JavaModeのPROCESSINGやJavaからは利用できません。

JavaModeのPROCESSINGやJavaでアニメーションを行いたい場合には、「java-universal-tween-engine 」や「Sprites for Processing」を利用すると良いでしょう。

そして嬉しいことに、java-universal-tween-engine と Sprites for ProcessingはPROCESSINGのAndroidModeでも動作します。

それぞれについては後日説明記事を起こす予定ですので、そちらを参照して下さい。

 

【詳細】

ObjectAnimatorの仕組み

ObjectAnimatorは対象となるオブジェクトのプロパティを、指定した時間内かつ指定した範囲内で線形変更する命令です。

通常はViewなどが持つプロパティを、指定した時間内で順次変更する事で、Viewがアニメーションする手助けをします。

例えばImageViewがもつAlphaプロパティを、3秒かけて1(不透明:100%)から0(透明:0%)に変化させると、ImageViewにセットされた画像が徐々に透明になるわけです。

またImageViewがもつtranslationXとtranslationYプロパティを変化させれば、ImegeViewの表示位置が変化するので、画像の移動が実現します。

ObjectAnimatorはView以外にも様々なオブジェクトのプロパティを変化させる事が可能ですが、対象となるオブジェクトには、操作したいプロパティを変更するためのセッターメソッドがある事が条件となります。

セッターメソッドとは、プロパティに値をセットするための専用関数の事です。例えばtranslationXというX座標を管理するプロパティがあったとして、これに値をセットするメソッド(setTranslationX())をセッターメソッドと呼びます。

ObjectAnimatorが扱うセッターメソッドの名前は、何でも良いというわけではなく、Javaの命名規則に従ってsetXxxxx(Xxxxxはプロパティ名)という名前である必要があります。


(画像URL:illust-AC 様:nomoさん、R-DESIGNさん)

ImageViewには、Alphaプロパティをセットする setAlpha() や、translationXプロパティをセットする setTranslationX() メソッドが備わっているため、ObjectAnimatorから直接 ImageViewオブジェクトを操作する事が可能となっているのです。

同じように、ObjectAnimatorでPROCESSINGのPImageを操作するなら、PImageに座標や透明度をセットするためのセッターメソッドが必要となります。しかし残念な事に、PImageにはそのようなプロパティやメソッドはありません。

ObjectAnimatorをPROCESSINGのオブジェクト(PImageなど)に適用したいなら、PImageを制御するための座標や透明度プロパティを持つクラス(プロパティ制御クラス)を用意して、そこに必要なプロパティとセッターメソッドを実装する工夫が必要となります。

(画像URL:illust-AC 様:nomoさん、K-factoryさん)

ObjectAnimatorで、プロパティ制御クラスにあるプロパティを変化させ、それをDraw関数などで読み取ってPImageに反映する事で、アニメーションを実現します。

 

プロパティ制御クラスの準備

まずは操作対象となるプロパティとセッターメソッドを持ったプロパティ制御クラスを用意します。

例えばこんな感じです。

ゲッターメソッドはSketchの中からプロパティ制御クラス内の各プロパティを読み取るのに利用します。

今回は縦横座標、透明度、拡大縮小率、回転角度、フレーム数といったプロパティを持つクラスを用意しましたが、どのようなプロパティを持つかは、どのようなアニメーションを行いたいかに応じてみなさんで工夫してください。

 

プロパティ変更:移動の例

float値を変化させるObjectAnimator oba = ObjectAnimator . ofFloat (Object target, String propertyName, float… values);

target : 対象となるオブジェクト
propertyName : プロパティ名
values : 変化させる範囲
oba : ObjectAnimator

ObjectAnimator.ofFloat() で、値の変化が設定された ObjectAnimator  を生成します。例えば上下移動するなら

といった感じになります。target には先程用意した PropertyControl クラスのインスタンスを与えます。

ポイントは ObjectAnimator . ofFloat() で、プロパティ名(この場合は translationY )と変化量( sy から sy + 100 まで )を指定している箇所です。

 

時間を指定するObjectAnimator oba = ObjectAnimator . setDuration (long duration);

duration: アニメーション時間(ms)
oba : ObjectAnimator

ObjectAnimator . setDurationでプロパティが変化する時間をミリセカンド単位で指定します。

こんな感じですね。

これで ObjectAnimator.ofFloat()で指定した動作が、100msかけて実行する準備が整いました。

 

プロパティの変更を開始するvoid ObjectAnimator .start ();

実際のプロパティの変更は、start() メソッドで開始します。

下記例では、画面にタッチされた時にプロパティの変更処理を開始しています。

ここでのポイントは、Property Animationによるプロパティの変更は必ず「UIスレッドで動作させる」という事です。

PROCESSINGは、(一部の特殊なメソッドを除き)UIスレッドではなく別スレッドで動作しています。プロパティの変更は必ずUIスレッドで動作させる必要があるため、このような記述を行っています。

UIスレッド以外でstart() メソッドを発行すると、例外エラーとなるので注意してください。

これで PropertyControl クラスのY方向のプロパティ(translationY)が、sy からsy + 100 まで100msで変化します。

実際にアニメーションを行う(イメージを動かす)ためには、draw() 関数の中から translationY プロパティを読み取って、指定された位置に画像を表示する必要があります。

全体のコーディングは下記のようになります。

 

プロパティ変更:透明度の例

透明度は transparency を変化させる処理を記述します。

こんな感じですね。

これでtarget に指定した PropertyControl クラスの transparency プロパティが 0 から 255 まで変化します。

あとは transparencyプロパティを元に画像の透明度を変化させる処理を draw() 関数の中に記述し、objectAnimator.start()でプロパティの変更を開始すればOKです。

たとえば、画像の透明度を変化させる draw()関数は下記のようになります。

 

プロパティ変更:並列に組み合わせる例

ここまでは単発のアニメーション例でしたが、これらを組み合わせるにはどうしたら良いでしょうか?。

例えば「横に移動しながら、徐々に大きくなる」などです。

これにはAnimatorSetクラスを利用する方法と、PropertyValuesHolderクラスを利用する方法があります。

AnimatorSetクラスについては後ほど紹介しますので、ここではPropertyValuesHolderクラスを利用する方法について記述します。

 

float値を変化させるPropertyValuesHolder pvf = PropertyValuesHolder . ofFloat (String propertyName,
float… values)

propertyName : プロパティ名
values : 変化させる範囲
pvf : PropertyValuesHolder

使い方は ObjectAnimator.ofFloat() 命令とほとんど一緒ですね(笑)。第一引数にターゲットを指定していないだけです。

例えば拡大縮小と横移動を行う操作は、以下のように記述できます。

拡大縮小率プロパティ(scaling)と、横座標プロパティ(translationX)を変化させています。

作成したPropertyValuesHolderは、ObjectAnimatorを使って並列化できます。

 

並列化するObjectAnimator oba = ObjectAnimator . ofPropertyValuesHolder (Object target,PropertyValuesHolder… values);

target : 対象となるオブジェクト
values : PropertyValuesHolder
oba : ObjectAnimator

ObjectAnimator.ofFloat() 命令と同じ要領で、作成したPropertyValuesHolderオブジェクトを並べて記述します。

ここで記述したPropertyValuesHolderオブジェクトは、アニメーションする際に並列実行(同時にアニメーション)されます。

左に100ピクセル移動しながら1.25倍に拡大する動作は

のようになります。

 

アニメーション:直列に組み合わせる例

それでは直列に組み合わせるには、どうしたら良いでしょうか?。

例えば「左に移動した後で、拡大する」などです。

これを実現するには、AnimatorSetクラスを利用します。

 

コンストラクタAnimatorSet animatorSet = new AnimatorSet();

直列化するvoid animatorSet.playSequentially ( Animator… items);

items : Animatorクラスを継承したオブジェクト

AnimatorSetは複数のアニメーションをまとめて、再生順番を指定するクラスです。

playSequentially命令は、引数で指定したアニメーションをシーケンシャル(記述した順番)で再生するように準備します。

この他にも、引数で指定したアニメーションを単発で再生するための play 命令、引数で指定したアニメーションを並列で再生するためのplayTogether命令などがあります。

 

再生時間を指定するAnimatorSet animatorSet = animatorSet.setDuration (long duration);

duration : アニメーション時間(ms)
animatorSet : AnimatorSet

AnimatorSetにも再生時間を指定する命令があります。使い方はObjectAnimator.setDuration() と一緒ですね。

 

再生するvoid animatorSet.start ();

start() 命令で再生を開始します。
以下の例では、画面にタッチした時に再生を開始しています。

アニメーションは必ず「UIスレッドで動作させる」という注意点も、ObjectAnimatorの場合と一緒です。

 

アニメーション:繰り返す例

アニメーションを繰り返すには注意が必要です。というのもAnimatorSetクラスには、繰り返しを指定する命令がないからです。

いろいろなサイト様を検索すると、クラスにAnimatorListenerやAnimatorListenerAdapterを実装し、onAnimationEndイベントで再度アニメーションを開始するように書かれています。

参考になるサイト様:

が・・・どうしたわけか、この方法ではPROCESSINGでアニメーションを繰り返す事ができませんでした。

結論から言うと、PROCESSINGでアニメーションを繰り返したい場合は、ObjectAnimatorに繰り返し回数と繰り返し動作を指定します。

 

繰り返し動作指定void oba . setRepeatMode (int repeatMode)

repeatMode : 繰り返し動作。ObjectAnimator.RESTART/REVERSE
oba : ObjectAnimator

RESTARTを指定すると最初から繰り返し、REVERSEを指定すると反転繰り返し(逆再生)になります。

 

繰り返し回数指定void oba . setRepeatCount (int repeatCount)

repeatCount : 繰り返し回数。0なら繰り返しなし。ObjectAnimator.INFINITEなら無限繰り返し
oba : ObjectAnimator

例えば下記のようになります。

この例では1.5倍に拡大する処理と、フレーム数(framerプロパティ)を0からMAXフレーム数まで変化させる処理を繰り返し行わせています。

 

【関連記事】

 


サンプルプログラム

繰り返しアニメーションする例:

詳細で説明したPropertyControlクラスがある前提です。

Assetsフォルダに、000.pngから009.png までの連番になった10枚の画像を用意しておきます。

画面にタッチすると拡大とフレームアニメーションを繰り返します。再度タッチすると一時停止します。

<出力サンプル>

(画像URL:らくがき。 様)※2018/06 Link先が見つかりません

下記はサンプルプログラムと同じ動きになるように、 P5.js で書き直したものです。動作イメージを確認できます。

P5.jsではマウスクリックでアニメーションを開始し、再クリックで一時停止するように変更しています。

なお一部のスマホ搭載ブラウザからは正しく表示されない場合があります。その場合はPCから閲覧してください。


(画像URL:らくがき。 様)※2018/06 Link先が見つかりません

 


PROCESSING逆引きリファレンス一覧 へ戻る

本ページで利用している「初音ミク」は、クリプトン・フューチャー・メディア株式会社 様に版権があります。「初音ミク」は、ピアプロ・キャラクター・ライセンスに基づいて掲載されています。

本ページで利用しているアイコン画像は、下記サイト様より拝借しております。各画像の著作権は、それぞれのサイト様および作者にあります。