ついにベールを脱いだJavaFX

第9回アニメーションを用いてより魅力的に[応用編]

前回は基本的なアニメーションということで、javafx.animation.Timelineクラスとjavafx.animation.KeyFrameクラスの使い方を紹介しました。今回は、応用編ということで、標準で提供されているさまざまなアニメーションについて紹介していきます。

今回、紹介するアニメーションはすべてjavafx.animation.transitionパッケージで定義されており、javafx.animation.transition.Transitionのサブクラスとなります。Transitionクラスは内部にアトリビュートとしてTimelineオブジェクトを保持しています。このため、Timelineクラスを使わずともアニメーションを実現することができます。

なお、今週使用したサンプルのソースを含めたNetBeansのプロジェクトは下記のリンクよりダウンロードすることができます。

移動、拡大・縮小、そして回転

前回のサンプルで移動のアニメーションを使用したように、移動のアニメーションはもっともよく使われるアニメーションの1つです。その他にも拡大・縮小と回転がよく使用されています。

そのため、これら3種類のアニメーションは、簡単に実現できるように専用のクラスが提供されています。それぞれ、移動がTranslateTransitionクラス、拡大・縮小がScaleTransitionクラス、回転がRotateTransitionクラスとなります。これら3つのクラスの使い方は共通しているので、ここでは回転を行うRotateTransitionクラスを使ってみましょう。

これらのクラスのスーパークラスであるTransitionクラスはnodeアトリビュートを持ちます。このnodeアトリビュートが回転や移動の対象となります。

リスト1
var node: Node = Group { ... };

var rotateTransition = RotateTransition {
    // 回転の対象ノード
    node: node
    
    // 回転角度の設定
    // 0度から720度回転させる
    fromAngle: 0
    byAngle: 720

    // これらのアトリビュートは Timeline クラスに準ずる
    duration: 5s
    repeatCount:4
    interpolate: Interpolator.EASEBOTH
    autoReverse: true
};

// 回転の開始
rotateTransition.play();

回転の角度を設定するには、開始角度と回転角度を指定する方法と、開始角度と終了角度を指定する方法があります。開始角度と回転角度は、それぞれfromAngleアトリビュートとbyAngleアトリビュートを設定します。開始角度と終了角度は、fromAngleアトリビュートとtoAngleアトリビュートで設定します。ここでは、青字で示したようにfromAngleアトリビュートとbyAngleアトリビュートを使用しました。

回転の中心はノードの中心です。もしノードの中心以外の点を回転中心にしたい場合は、ダミーの透明なノードで中心を調節するか、RotateTransitionクラスを使わずに直接Timelineクラスを使用するようにします。

durationアトリビュートやrepeatCountアトリビュートなどはTimelineクラスを使用した時と同じです。補間方法はKeyFrameクラスではtween演算子を使用しましたが、ここではinterpolateアトリビュートで指定します。

最後にアニメーションを開始させるため、play関数をコールします。タイムラインを制御するplay関数などの関数もTimelineクラスと同じです。

次にノードを表示する部分を示します。

リスト2
Stage {
    title: "Rotate Sample"
    scene: Scene {
        width: 200
        height: 200
        content: [
            node
        ]
    }
}

特に難しい部分は何もありません。単に変数nodeを描画しているだけです。ここでは変数nodeは6つの円としました。

リスト3
def radian = Math.PI / 180.0;

var node: Node = Group {
    translateX: 100
    translateY: 100
 
    // 6個の円
    content: [
        for (angle in [0..300 step 60]) {
            Circle {
                centerX: 50.0 * Math.cos(angle * radian);
                centerY: -50.0 * Math.sin(angle* radian);
                radius: 35
                fill: Color.PINK
                stroke: Color.RED
            }
        },
        // 重ね順を調節するための半円
        Arc {
            centerX: 50,
            centerY: 0
            radiusX: 35,
            radiusY: 35
            startAngle: 180,
            length: 180
            type: ArcType.OPEN
            fill: Color.PINK
            stroke: Color.RED
        }
    ]
};

最後のArcオブジェクトがないと、最後の円が一番上になってしまいます。そこで、Arcオブジェクトで最初の円の一部を上書きしています。このようにすることで、すべての円が一部隠れるようになります。

実行結果を図1に示します。いつもと同じようにこの図もアプレットページへのリンクになっています。これ以降も実行結果の図はアプレットのページへのリンクになっています。また、スクリプトも記載しておきますので、参考になさってください。

図1 回転する円の実行結果

図1 回転する円の実行結果

フェードイン、フェードアウト

次に行うのが、透明から出現したり、透明になって消えていくフェードイン、フェードアウトです。ここで使用するのはFadeTransitionクラスです。FadeTransitionクラスもRotateTransitionクラスと同じようにnodeアトリビュートがフェードイン、フェードアウトの対象となります。

リスト4
var fadeTransition = FadeTransition {
    // フェードの対象となるノード
    node: blurredStar
 
    // 不透明度を 0.3 から 1.0 まで変化させる
    fromValue: 0.3
    toValue: 1.0
 
    duration: 0.5s
    repeatCount: Timeline.INDEFINITE
    autoReverse: true
};
fadeTransition.play();

フェードイン、フェードアウトの指定はfromValueアトリビュートとtoValueアトリビュートによって決まります。それぞれ不透明度を表しており、0で透明、1で不透明になります。fromValueアトリビュートの方が値が小さい場合はフェードインになり、大きい場合はフェードアウトになります。

他のアトリビュートはRotateTransitionクラスと同じです。ここでは、フェードイン、フェードアウトを使って星をまばたかせてみました。星をまばたかせるために、まず星形を描画し、その後ろで星形をぼかしたノードに対してフェードイン、フェードアウトを繰り返し行います。

星形を作るにはjavafx.scene.shape.Pathクラスを使用しました。PathクラスはJavaのjava.awt.geom.Path2Dクラスに相当するクラスで任意の直線や曲線を組み合わせてパスを作成します。Path2DクラスがlineToメソッドやcurveToメソッドなどで手続き的にパスを構築するのに対し、PathクラスはLineToクラスやCubicCurveToクラスなどjavafx.scene.shape.PathElementクラスのサブクラスを使用して構造的にパスを構築します。

ぼかしを行うにはNodeクラスのeffectアトリビュートを使用します。effectアトリビュートの型はjavafx.scene.effect.Effectクラスです。Effectクラスのサブクラスにはドロップシャドウを行うDropShadowクラスや、色をセピア調にするSepiaToneクラスなどさまざまなクラスがあります。ぼかしを行うにはGaussianBlueクラスを使用します。

以下に星形と星形をぼかしたノードを作成するスクリプトを示します。

リスト5
// 星の形を表す PathElement
var starElements: PathElement[] = [
    MoveTo { x: 0       y: -50 },
    LineTo { x: 11.803  y: -11.804 },
    LineTo { x: 50      y: -11.804 },
    LineTo { x: 19.098  y: 11.804 },
    LineTo { x: 30.902  y: 50 },
    LineTo { x: 0       y: 26.394 },
    LineTo { x: -30.902 y: 50 },
    LineTo { x: -19.098 y: 11.804 },
    LineTo { x: -50     y: -11.804 },
    LineTo { x: -11.803 y: -11.804 },
    ClosePath {}
];

// 星形
var star: Node = Path {
    translateX: 100
    translateY: 100
    fill: Color.web("#CCCC00")
    stroke: null
    
    elements: starElements
};

// ぼかした星形
var blurredStar: Node = Path {
    translateX: 100
    translateY: 100
    fill: Color.web("#FFFF00")
    stroke: null

    // ぼかしをかける
    effect: GaussianBlur {
        radius: 20
    }

    elements: starElements
};

星形を表すPathElementオブジェクトのシーケンスは、星形と星形のぼかしで同一なので、変数starElementsとして括りだしてあります。

最後に星形と星形のぼかしを描画する部分を示します。

リスト6
Stage {
    title: "Fading Sample"
    scene: Scene {
        width: 200
        height: 200
        fill: LinearGradient {
            startX: 0.0, startY: 0.0, endX: 0.0, endY: 1.0
            proportional: true
            stops: [
                Stop { offset: 0.0 color: Color.web("#000022") },
                Stop { offset: 1.0 color: Color.web("#000066") }
            ]
        }
 
        content: [blurredStar, star]
    }
}

夜空を表すため、背景はグラデーションで塗っています。

では、このスクリプトを実行してみましょう。まばたいているように見えるでしょうか?

図2 まばたく星

図2 まばたく星

パスに沿った移動

今まで扱ってきた移動のアニメーションは移動元の座標から、移動先の座標へ直線的に移動するものでした。でも、曲がった軌跡をたどって移動するアニメーションなども行ってみたいと思いませんか。

もちろん、曲線といえども、とても短い区間を取りだしてみれば直線として扱えます。したがって、その短い区間ごとにKeyFrameオブジェクトで軌跡を作り込んでいけば、曲がった軌跡もできなくはありません。しかし、ちょっと考えただけでも、大変そうだと想像がつきます。

Adobe Flashではモーションガイドと呼ばれるパスを設定して、そのパスに沿って移動するアニメーションを作成することができます。同じことを実現するために、JavaFX ScriptではPathTransitionクラスが提供されています。

アニメーションのガイドとなるパスはjavafx.animation.transition.AnimationPathクラスで表します。しかし、AnimationPathクラスのオブジェクトを直接生成することはできません。AnimationPathオブジェクトを生成するにはcreateFromPath関数を使用します。引数の型はPathクラスです。

これをスクリプトで表すと次のようになります。アニメーションはガイドパスの起点から終点までアニメーションしながら移動します。残念ながら、Adobe Flashのようにパスの途中から移動するなどのアニメーションはできませんが、それでもKeyFrameオブジェクトで表すよりは簡単にパスに沿って移動するアニメーションが実現できます。

リスト7
// パスに沿って移動するノード
var node: Node = ...
 
// ガイドとなるパス
var guidePath = Path { ... }
 
var pathTransition = PathTransition {
    node: node
 
    path: AnimationPath.createFromPath(guidePath)
}

// アニメーションの開始
pathTransition.play();

ここでは花をらせんに沿って移動させてみました。

花は花びらを作成し、90度ずつ回転させて作りました。花びらはPathクラスで表し、ベジェ曲線(CubicCurveToクラス)と円弧(ArcToクラス)を使って作成しています。

リスト8
var node: Node = Group {
    content: [
        // 90 度ずつ回転させた花びらを 4 枚
        for (angle in [0, 90, 180, 270]) {
            Path {
                stroke: null
                fill: RadialGradient {
                    centerX: 0.5 centerY: 1.0
                    stops: [
                        Stop { offset: 0.0 color: Color.web("#FFEEEE") },
                        Stop { offset: 0.8 color: Color.PINK }
                    ]
                }
 
                // (0, 0) を中心に回転
                transforms: Rotate { pivotX: 0.0 pivotY: 0.0 angle: angle }
 
                elements: [
                    MoveTo { x: 0 y: 0},
                    CubicCurveTo {
                        x: 7.321 y: -12.68
                        controlX1: 0 controlY1: 0
                        controlX2: 7.321 controlY2: -8.68
                    },
                    ArcTo {
                        x: -7.321 y: -12.68
                        radiusX: 7.32 radiusY: 7.32
                    },
                    CubicCurveTo {
                        x: 0 y: 0
                        controlX1: -7.321 controlY1: -8.68
                        controlX2: 0 controlY2: 0
                    },
                ]
            }
        }
    ]
}

ガイドとなるパスはらせんにしました。いわゆる蚊取り線香のようならせんで、一様らせん、もしくはアルキメデスのらせんと呼ばれているらせんです。一様らせんはx=αθsinθ, y=αθcosθで表すことができます。

以下にらせんを作成している部分を示します。角度を15度で分割し、その間の弧を直線で近似させてしまっていますが、それほどカクカクになることはありません。

リスト8
// 度からラジアンへの変換係数
def TO_RADIAN = Math.PI/180.0;
 
// node を移動させるガイドパス
var guidePath = Path {
    elements: [
        MoveTo { x: 100 y: 100 },
        for (deg in [0.0..1800.0 step 15.0]) {
            // 度からラジアンに変換
            var rad = deg * TO_RADIAN;
            LineTo {
                x: 2.0 * rad * Math.sin(rad) + 100
                y: 2.0 * rad * Math.cos(rad) + 100
            }
        }
    ]
}

Stageオブジェクトを作成する部分は今までのサンプルと同じなので、省略させていただきました。最後にアニメーションを行う部分を示します。

リスト9
var pathTransition = PathTransition {
    // パスに沿って移動する対象ノード
    node: node

    // パスから AnimationPath オブジェクトを作成
    path: AnimationPath.createFromPath(guidePath)
 
    // パスに沿って回転
    orientation: OrientationType.ORTHOGONAL_TO_TANGENT
 
    duration: 10s
    repeatCount:4
    autoReverse: true
}
pathTransition.play();

赤字で示したorientationアトリビュートはノードがパスに沿って移動する時に、パスの傾きに応じて回転するかどうかを示します。デフォルトでは回転を行わないOrientationType.NONEとなっています。

パスに沿って回転させる場合は、リスト9のスクリプトのようにOrientationType.ORTHOGONAL_TO_TANGENTを指定します。

図3 らせんにそって移動する花

図3 らせんにそって移動する花

複数のアニメーションを順番に行う

ここまでは単体のアニメーションを扱ってきましたが、複数のアニメーションを組み合わせたいこともあります。このような場合、SequentialTransitionクラスもしくはParallelTransitionクラスを使用します。

この2つのクラスの違いは、SequentialTransitionクラスが複数のクラスを順々にシーケンシャルに実行するのに対し、ParallelTransitionクラスが複数のアニメーションを同時にパラレルに実行することにあります。

そこで、本節ではSequentialTransitionクラス、次節でParallelTransitionクラスを説明します。

SequentialTransitionクラスはcontentアトリビュートを持ちます。contentアトリビュートの型はTransitionクラスのシーケンスであり、ここに順番に実行するアニメーションを記述していきます。SequentialTransitionオブジェクトのplay関数をコールすると、contentアトリビュートの最初のアニメーションを実行し、終了したら次のアニメーションを実行し、というように順々にアニメーションを行います。

たとえば、次の例では移動、回転、拡大という順番でアニメーションが行われます。

リスト10
var seqTransition = SequentialTransition {
    // アニメーションの対象となるノード
    node: node
    
    // シーケンシャルに実行するアニメーション
    content: [
        TranslateTransition {
            duration: 2s
            fromX: 20
            fromY: 20
            toX: 100
            toY: 100
        },
        RotateTransition {
            duration: 1s
            fromAngle: 0
            byAngle: 360
        },
        ScaleTransition {
            duration: 2s
            byX: 2
            byY: 2
        }
    ]
}
seqTransition.play();

SequentailTransitionクラスのnodeアトリビュートが、contentアトリビュートに指定されたアニメーションの対象になります。contentアトリビュートの要素となる個々のアニメーションでnodeアトリビュートを指定していた場合、個々のアニメーションのnodeが優先されます。

また、特別なアニメーションとして、指定した時間なにも行わないPauseTransitionクラスがあります。シーケンシャルにアニメーションを行う途中に休止時間を設けたい時などに使用することができます。

ここでは、先ほどの星形を四角の縁にあわせて移動させるアニメーションを作ってみました。角に来ると1回転するようにしてあります。さきほどのサンプルのままだと星が大きすぎるので、scaleXアトリビュートとscaleYアトリビュートにそれぞれ0.25を代入して、縮小してあります。

以下にSequentialAnimationクラスを使用する部分を示します。

リスト11
var seqTransition = SequentialTransition {
    // アニメーションの対象となるノード
    node: star

    // シーケンシャルに実行されるアニメーション
    content: [
        TranslateTransition {
            duration: 2s
            fromX: 20
            fromY: 20
            toX: 180
            toY: 20
        },
        PauseTransition {
            duration: 0.5s
        },
        RotateTransition {
            duration: 1s
            fromAngle: 0
            byAngle: 360
        },
        TranslateTransition {
            duration: 2s
            fromX: 180
            fromY: 20
            toX: 180
            toY: 180
        },
        PauseTransition {
            duration: 0.5s
        },
        RotateTransition {
            duration: 1s
            fromAngle: 0
            byAngle: 360
        },
        TranslateTransition {
            duration: 2s
            fromX: 180
            fromY: 180
            toX: 20
            toY: 180
        },
        PauseTransition {
            duration: 0.5s
        },
        RotateTransition {
            duration: 1s
            fromAngle: 0
            byAngle: 360
        },
        TranslateTransition {
            duration: 2s
            fromX: 20
            fromY: 180
            toX: 20
            toY: 20
        },
        PauseTransition {
            duration: 0.5s
        },
        RotateTransition {
            duration: 1s
            fromAngle: 0
            byAngle: 360
        }
    ]
}
seqTransition.play();

このスクリプトでは星形を移動、休止、回転させることを繰り返しています。

ここで、一連のアニメーションを繰り返してみようと、SequentialTransitionクラスのrepeatCountアトリビュートを設定して実行してみたのですが、正しく動作しません。SequentialTransitionクラスのAPIドキュメントを見てみると、duration、repeatCountおよびautoReverseは使用できないことが記述されています。

もし、繰り返し実行を行いたい場合は、以下のようにTimelineオブジェクトを作成し、KeyFrameオブジェクトのactionアトリビュートの中でSequentialTransitionオブジェクトのplayFromStart関数を繰り返しコールするようにします。

リスト12
Timeline {
    repeatCount: Timeline.INDEFINITE
    keyFrames : [
        KeyFrame {
            time : 0s
            action : function() {
                seqTransition.playFromStart();
            }
        },
        KeyFrame {
            time : 14s
        }
    ]
}.play();

14秒にKeyFrameオブジェクトがあるのは、14秒のループを作るためです。では、0 秒の時にplayFromStart関数をコールするのではなく14秒の時に行えばいいように感じますが、そうするとサンプルを起動してから14秒間無反応になってしまうのです。

実行結果を図4に示します。

図4 シーケンシャルに移動する星

図4 シーケンシャルに移動する星

複数のアニメーションを同時に行う

今度は複数のアニメーションを同時に行ってみます。ParallelTransitionクラスの使い方はSequentialTransitionとほぼ同じです。しかし、contentアトリビュートに列記したアニメーションが同時に行われることが異なります。

先ほど作成した花がらせん状に移動するスクリプトは花の回転がちょっと少なすぎたように感じるので、ここではらせんに沿った移動と回転を同時に行ってみましょう。ついでに、花が外側にくるほど大きくなるようにしてみました。

リスト13
var parTransition = ParallelTransition {
    node: node
    content: [
    	// らせんに沿って移動
        PathTransition {
            path: AnimationPath.createFromPath(guidePath)
            orientation: OrientationType.ORTHOGONAL_TO_TANGENT
            duration: 10s
            repeatCount: 2
            autoReverse: true
            interpolate: Interpolator.EASEBOTH
        },
        // 回転
        RotateTransition {
            fromAngle: 0
            byAngle: 1800
            duration: 10s
            repeatCount: 2
            autoReverse: true
            interpolate: Interpolator.EASEBOTH
        },
        // 拡大
        ScaleTransition {
            byX: 1.5
            byY: 1.5
            duration: 10s
            repeatCount: 2
            autoReverse: true
            interpolate: Interpolator.EASEBOTH
        }
    ]
}
parTransition.play();

ParallelTransitionクラスもSequentialTransitionクラスと同様duration、autoReverse、repeatCountの各アトリビュートは使用することができません。しかし、同時に実行するアニメーションの時間がすべて同じであれば、個々のアニメーションのautoReverseアトリビュートをtrueにすることでアニメーションを反転させるように見せることができます。

上述のスクリプトではすべてアニメーションの時間が10秒なので、autoReverseをtrueにすることでアニメーションを反転させています。また、アニメーションを繰り返すにはSequentialTransitionクラスと同じように、別個にTimelineクラスを使うことで実現できます。

回転しながららせんに沿って移動する花の実行結果を図5に示しました。

図5 らせんに沿って移動する花

図5 らせんに沿って移動する花

モーフィング

最後におまけ的なアニメーションを紹介しましょう。モーフィングとは2つの形状を自然に変形させることをいいます。

JavaFXでは簡単なモーフィングを行うためにjavafx.scene.shape.DelegateShapeクラスが用意されています。⁠簡単な」というのは、モーフィングを行う対象がShapeクラスのサブクラスに限定されているからです。

とはいえ、シェイプといえばPathクラスもあるのでスクリプトで任意の形状を定義できます。使い方によってはインパクトのある効果を作り出すこともできるはずです。

DelegateShapeクラスは単独で使用するのではなく、Timelineクラスと共に使うことでモーフィングを行います。たとえば、四角から円にモーフィングさせるには以下のように記述します。

リスト14
var rectangle = Rectangle {
    x: -50 y: -50 width: 100 height: 100
}

var circle = Circle {
    centerX: 0 centerY: 0 radius: 40
}

var shape: Shape;

Stage {
    title: "Morphing"
    scene: Scene {
        width: 200 height: 200
        
        content: DelegateShape {
            // モーフィングする対象
            shape: bind shape

            translateX: 100 translateY: 100
            fill: Color.RED
        }
    }
}

Timeline {
    keyFrames: [
        KeyFrame {
            time: 0s values: shape => rectangle
        },
        KeyFrame {
            time: 5s values: shape => circle

        }
    ]
}.play();

DelegateShapeクラスはshapeアトリビュートを持ち、ここに変形させるシェイプを指定します。シェイプは変化するのでbindをお忘れなく。

そして、Timelineオブジェクトでシェイプを変化させます。ここでは、青字で書いたように四角から円に変化させています。このようにすることでアニメーションで四角から円へ変形を行います。図6は四角から円への変形の途中の段階を示しています。

図6 四角から円へのモーフィング
図6 四角から円へのモーフィング

DelegateShapeクラスを使う時の注意点として、変形させるシェイプオブジェクトではtranslateXアトリビュートやtransformアトリビュートなどの移動、回転、拡大・縮小はすべて無視されるということがあります。そのため、⁠0, 0)を中心にシェイプを定義するようにするのがお勧めです。また、シェイプオブジェクトでは色も無視されます。これらのアトリビュートはDelegateShapeオブジェクトで指定された値が適用されます。

では、先ほどから何度も登場している星と花を題材にモーフィングしてみましょう。

ところで、星はPathクラスで定義していたのでシェイプですが、花はGroupクラスで定義したのでシェイプではありません。しかし、花びらはPathクラスで定義したので、花びら4枚分をPathクラスで表すのはそれほど大変ではありません。ただし、スクリプトが長くなってしまったので、詳細はリンク先のアプレットのページでご確認ください。

ここでは、モーフィングと一緒に色を変更し、シェイプにはドロップシャドウも付加してあります。また、星と花に円を加えてモーフィングするようにしました。DelegateShapeクラスとTimelineクラスを使用する部分を以下に示します。

リスト15
var shape: Shape;
var color: Color;

Stage {
    title: "Morphing Sample"
    scene: Scene {
        width: 200
        height: 200
        fill: LinearGradient {
            startX: 0.0, startY: 0.0, endX: 0.0, endY: 1.0
            proportional: true
            stops: [
                Stop { offset: 0.0 color: Color.WHITE },
                Stop { offset: 0.5 color: Color.LIGHTGRAY }
            ]
        }

        content: DelegateShape {
            // モーフィングする対象
            shape: bind shape

            // 色もいっしょに変更する
            fill: bind color

            // ドロップシャドウ
            effect: DropShadow {
                offsetX: 5
                offsetY: 5
                radius: 5
            }

            translateX: 100
            translateY: 100
        }
    }
}

var timeline = Timeline {
    repeatCount: Timeline.INDEFINITE
    keyFrames: [
        KeyFrame {
            // 星
            time: 0s
            values: [
                shape => star,
                color => Color.YELLOW
            ]
        },
        KeyFrame {
            // 星から花
            time: 5s
            values: [
                shape => flower,
                color => Color.PINK
            ]
        },
        KeyFrame {
            // 花から丸
            time: 10s
            values: [
                shape => circle,
                color => Color.RED,
            ]
        },
        KeyFrame {
            // 丸から星
            time: 15s
            values: [
                shape => star,
                color => Color.YELLOW
            ]
        }
    ]
};
timeline.play();

星から花、花から丸、丸から星とモーフィングを繰り返します。実行結果を図7に示しました。モーフィングを行っている途中であっても、ドロップシャドウが途中の形状に追従していることがわかります。

図7 星から花へのモーフィング

図7 星から花へのモーフィング

このように、単純なシェイプであればモーフィングを行うことが可能です。しかし、少し複雑な形状になると、思ったように形状が変化してくれません。残念ながら、現状のJavaFX Scriptでは変更前のシェイプと変換後のシェイプとの間で対応する箇所を示すヒントをつけることができません。ヒントが使えるようになれば、複雑な形状でも意図したようにモーフィングにすることができるので、活用できる場面も増えるのです。今後のアップデートに期待しましょう。

さて、2回に渡ってアニメーションについて解説してきましたが、いかがでしたでしょうか。アニメーションは効果的に使えばユーザビリティを向上することが可能です。ぜひ、活用していただければと思います。

おすすめ記事

記事・ニュース一覧