複雑なアニメーション

JavaFX はアニメーションを簡単に書けるのですが、いざやってみるとどうやって書けばいいか分からないことも多々あります。意外に多いのが、複数のアニメーションを組み合わせること。

複数のアニメーションを同時に行うのであれば ParallelTransition クラス、1 つ 1 つシーケンシャルに行いたいのであれば SequentialTransition クラスを使うことができます。

ところが、全部同時とか、シーケンシャルというのは少なくて、下の絵のように個々のアニメーションがばらばらなことが多いわけです。

f:id:skrb:20120612210726p:image

こういう場合も、SequentialTransition クラスと ParallelTransition クラスを組み合わせれば書けないことはないのですが、それなりにめんどうです。

じゃあ、どうすればいいかというとメインの時間軸を設定しておいて、そこに各アニメーションをくっつけていくような感じにします。

Flash Professional を使っている人はすぐ分かると思うのですが、これって Flash のタイムラインにレイヤーを作ってムービークリップをそこに設定したり、トゥイーンを設定するのと同じです。

f:id:skrb:20120612212250p:image

では実際にやってみましょう。たとえば、500ms たったら animation1、1000ms たったら animation2 をキックするようにしてみます。

        // 基本となる時間軸
        Timeline timeline = new Timeline(
            new KeyFrame(
                new Duration(500),
                new EventHandler<ActionEvent>() {
                    @Override
                    public void handle(ActionEvent event) {
                        // アニメーション1を開始
                        animation1.play();
                    }
                }             
            ),
            new KeyFrame(
                new Duration(1000),
                new EventHandler<ActionEvent>() {
                    @Override
                    public void handle(ActionEvent event) {
                        // アニメーション2を開始
                        animation2.play();
                    }
                }     
            )
        );

        timeline.play();

こんな感じです。

JavaFX Script の頃はアニメーションの入れ子ができたので、もうちょっと簡単に書けたのですが、しかたありません。でも、Java 8 の Lambda 式を使えるようになれば、もうちょっとスッキリするはず。

実際に動作する例を出しておきましょう。四角と丸がバラバラにアニメーションする例です。

アニメーション自体はたいしたことがないので、どうやって組み合わせているかだけでも見ていただければと思います。

組み合わせているのは

  • 四角のフェードイン
  • 四角の左右の移動
  • 四角の色の変化
  • 丸のフェードイン
  • 丸のサイズの変化
  • 丸のフェードアウト

の 5 つです。

各アニメーションが final になっているのは、EventHandler インタフェースの無名クラスの中で起動しているからです。ここではベタに書きましたけど、もうちょっと工夫すれば final を書かない書き方もできますね。

f:id:skrb:20120612235636p:image

で、こういうようにアニメーションを組み合わせると、こんなのもできるようになるわけです。


JavaFX animation sample - Duke

実際に、このアニメーションをどうやって書いたかは、またいつか書きます。