JavaFXのアニメーション機能

JavaFXにはさまざまなアニメーション機能が含まれている。TransitionTimelineなどのクラスを使って、グラフィックを動かしてみよう。

TranslateTransitionを使う

JavaFXがSwingなどに比べて優れている点の1つが「アニメーション」である。Swingでグラフィックをアニメーションさせようとすると、スレッドやタイマーを作成し、位置を頻繁に移動して再描画する処理を繰り返す必要があった。しかしJavaFXなら、アニメーションを簡単に作成できる。

アニメーション関連の機能はjavafx.animationパッケージにいろいろ用意されている。まずはもっともよく使われる「表示位置を移動する」ものから使ってみよう。

これはTranslateTransitionというクラスとして提供されている。アニメーション関連クラスの中でも基本となるものだ。このクラスの使い方がわかれば、他のクラスもだいたい同じように扱える。

TranslateTransitionは次のような形でインスタンスを作成する。

new TranslateTransition();
new TranslateTransition("Duration");
new TranslateTransition("Duration", "Node");

引数なしのものから、DurationNodeを持つものまで、いくつかのコンストラクタが用意されている。引数のNodeは動かす部品のインスタンスである。グラフィックであれば、シェイプ関連のインスタンスをここに指定する。

もう1つのDurationjavafx.utilパッケージに含まれるクラスで、アニメーションの経過時間を扱うためのものだ。これは次のようにインスタンスを作成する。

new Duration(ミリ秒);

これにより、引数に指定したミリ秒単位の経過時間を表すDurationインスタンスを利用できる。これで「どの図形を、どれくらいの時間でアニメーションとして動かすか」という基本設定ができる。

なお、コンストラクタでNodeDurationを設定しなかった場合は、後からメソッドで指定する必要がある。

"TranslateTransition".setNode ( "Node");
"TranslateTransition".setDuration ( "Duration");

これらがないとアニメーション自体が成立しないため、最初からコンストラクタの引数で指定しておくとよい。

アニメーション設定メソッド

TranslateTransitionインスタンスを作成したら、続けてメソッドを呼び出してアニメーションの細かな設定を行う。さまざまなメソッドが用意されているが、まず必要になるものは次のとおりである。

移動前の位置を設定するメソッド

"TranslateTransition".setFromX("double");
"TranslateTransition".setFromY("double");
"TranslateTransition".setFromZ("double");

移動先の位置を設定するメソッド

"TranslateTransition".setToX("double");
"TranslateTransition".setToY("double");
"TranslateTransition".setToZ("double");

オートリバース設定

"TranslateTransition".setAutoReverse("boolean");

繰り返し回数設定

"TranslateTransition".setCycleCount ( "int");

ひととおり設定したら、最後にTranslateTransitionplayメソッドを呼び出してアニメーションを開始する。途中で停止するstoppauseといったメソッドも用意されている。いずれも引数なしで呼び出すだけである。

簡単な使用例は次のとおりである。

// import javafx.animation.*;
// import javafx.util.Duration;
 
public void createShape(Pane root){
    Rectangle r = new Rectangle(20, 20, 50, 50);
    r.setFill(Color.CYAN);
    root.getChildren().add(r);
    new TranslateTransition();
     
    TranslateTransition tt = new TranslateTransition(new Duration(1000), r);
    tt.setFromX(20);
    tt.setToX(100);
    tt.setAutoReverse(true);
    tt.setCycleCount(10);
    tt.play();
}

これまでと同じクラスを使い、図形を作成するcreateShapeメソッドを書き換える形でまとめている。実行すると、表示された四角形が左右に往復運動する。

アニメーション用の主なクラス

TranslateTransitionのようなアニメーション用クラスは、他にもいろいろ用意されている。重要なものを整理しておく。

リサイズアニメーション

new ScaleTransition("Duration", "Node");

設定メソッド

"ScaleTransition".setFromX("double");
"ScaleTransition".setFromY("double");
"ScaleTransition".setFromZ("double");

"ScaleTransition".setToX("double");
"ScaleTransition".setToY("double");
"ScaleTransition".setToZ("double");

回転アニメーション

new RotateTransition ( "Duration", "Node");

設定メソッド

"RotateTransition".setFromAngle ( "double");
"RotateTransition".setToAngle ( "double");

色のアニメーション

new FillTansition("Duration", "Node");
new FillTansition("Duration", "Node", "Color1", "Color2");

new StrokeTransition("Duration", "Node");
new StrokeTransition("Duration", "Node", "Color1", "Color2");

設定メソッド

"StrokeTransition".setFromValue("Color");
"StrokeTransition".setToValue("Color");

フェードアニメーション

new FadeTransition("Duration", "Node");

設定用メソッド

"FadeTransition".setFromValue("double");
"FadeTransition".setToValue("double");

基本的な使い方はすべてTranslateTransitionと同じである。DurationNodeを引数に指定してインスタンスを作り、メソッドでアニメーション前後の値を設定し、setAutoReverseや繰り返し回数などを調整してからplayで開始する、という流れになる。

TranslateTransitionを使えるようになれば、これらのクラスもほぼ同じ感覚で利用できる。

Timelineを使う

これまでのクラスは、基本的に「現在の状態から次の状態へ変化する」という2つの状態をなめらかに切り替えるアニメーションを簡単に作るためのものだった。より複雑な動きを実現するために、これらをいくつもつなげていくのは効率的ではない。

そのような場合に使うのがTimelineクラスである。Timelineは文字どおり、アニメーションのタイムライン、つまり時間ごとの変化を管理するものになる。

Timelineを使うにはKeyFrameクラスが必要である。これはタイムラインに設定するキーフレーム、つまり特定の時間におけるアニメーションの状態を表すものだ。

Timelineはまずインスタンスを作成し、そこに必要に応じてKeyFrameを組み合わせていく。必要な設定ができたらplayでアニメーションを開始する流れになる。必要なものを整理しておこう。

Timelineを作成する

new Timeline();

Timelineインスタンスは引数なしのデフォルトコンストラクタで作成できる。それ自体には、これまでのアニメーションクラスのようにNodeDurationなどを設定しない。

KeyFrameを作成する

new KeyFrame("Duration", "KeyValue");

KeyFrameは引数にDurationKeyValueのインスタンスを指定する。Durationは前に登場した、アニメーションの再生時間を扱うインスタンスである。

KeyValueは、キーに設定する値を扱うクラスである。これは次のように作成する。

KeyValueを作成する

new keyValue("Property 値");

KeyValueは、プロパティを表すPropertyインターフェースを実装するクラスと、そこに設定する値を引数に指定する。シェイプのプロパティなどは、その多くがPropertyインターフェースを実装して作られており、プロパティを表すPropertyインスタンスを取り出すメソッドが用意されている。それを利用して、対象シェイプのプロパティを表すPropertyインスタンスと設定値からKeyValueを作成する。

これでアニメーションに必要なTimelineKeyFrame、そしてKeyFrameに必要なKeyValueが用意できた。次に、これらをもとにアニメーション情報を組み立ててみよう。

Timelineでアニメーションを表示する

作成したTimelineには、アニメーションに関するさまざまな設定メソッドが用意されている。これらを使って必要な情報を組み立てる。主なメソッドを整理しておく。

オートリバース設定

"Timeline".setAutoReverse("boolean");

アニメーションを往復再生する設定である。trueにするとオートリバースが有効になる。

再生回数設定

"Timeline".setCycleCount("int");

アニメーションの再生回数を整数で指定する。

KeyFrameを管理するListを取得する

"Timeline".getKeyFrames ();

Timelineに設定されているKeyFrameは、List (ObservableList)インスタンスにまとめられてTimelineに保持されている。このListを取得するのがgetKeyFramesである。

KeyFrameを追加する

"ObservableList".add("KeyFrame");

TimelineKeyFrameを設定するには、getKeyFramesListを取得し、addメソッドで追加する。これでKeyFrameが追加される。

それでは実際に、Timelineを使ったアニメーションサンプルを作ってみよう。次はcreateShapeメソッドを書き換えたものである。

// import javafx.animation.*;
// import javafx.util.Duration;
 
public void createShape(Pane root){
    Rectangle r = new Rectangle(20, 20, 100, 50);
    r.setFill(Color.CYAN);
    root.getChildren().add(r);
     
    Timeline tl = new Timeline();
    tl.setAutoReverse(true);
    tl.setCycleCount(10);
 
    // 가로 작업 KeyFrame 작성
    KeyFrame key_a1 = new KeyFrame(
        new Duration(0),
        new KeyValue(r.widthProperty(),100));
    KeyFrame key_a2 = new KeyFrame(
        new Duration(2500),
        new KeyValue(r.widthProperty(),200));
 
    // 채우기 색 작업 KeyFrame 작성
    KeyFrame key_b1 = new KeyFrame(
        new Duration(0),
        new KeyValue(r.fillProperty(),Color.rgb(255, 0, 0)));
    KeyFrame key_b2 = new KeyFrame(
        new Duration(2500),
        new KeyValue(r.fillProperty(),Color.rgb(0, 0, 255)));
    tl.getKeyFrames().add(key_a1);
    tl.getKeyFrames().add(key_a2);
    tl.getKeyFrames().add(key_b1);
    tl.getKeyFrames().add(key_b2);
    tl.play();
}

これを実行すると、四角形の色が赤から青の間で変化しながら、幅が伸びたり縮んだりする。

ここではRectangleの幅プロパティを取得するためにwidthPropertyメソッドを使っている。これはdouble値のプロパティであるDoublePropertyを取得する。

また、塗りつぶし色を取得するためにfillPropertyメソッドを使っている。これはColorを値とするPropertyである。引数にはColorクラスのrgbメソッドを使い、RGBそれぞれの明るさを指定して色を設定している。

Timelineをうまく扱えるようになれば、さまざまなプロパティの値を自由に操作して動かせるようになる。Nodeにどのような操作可能なプロパティがあるか調べてみると面白いだろう。