より複雑なQMLアニメーションの作成

Advanced QML animation
前回では簡単なQMLアニメーションを紹介しました。今回はより凝ったアニメーションの制作方法を紹介します。

PathAnimationを使うと、パスに沿った移動をアイテムに施せます。パスにはsvg形式のテキストも使えるので、InkScapeなどのsvgエディタをアニメーションエディタの代わりに使用することができます。
path.qml
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Layouts 1.0
import QtQuick.Controls 1.0

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("PathAnimation")

    ColumnLayout{
        Label{
            id: lblHello
            text: "Hello!"

            transitions: [
                Transition{
                    to: "move"
                    PathAnimation{
                        target:lblHello
                        duration: 5000
                        path:Path{
                            // (100, 100)にジャンプ
                            PathMove{ x: 100; y: 100 }
                            // (200, 200)へ直線移動
                            PathLine{ x: 200; y: 200 }
                            // SVG形式のパスに沿って移動
                            PathSvg{ path:"m 200,200 c 0,0 38,-47 63,0 24,50 -60,25 -37,50 23,25 80,20"}
                        }
                    }
                }
            ]
        }

        Button{
            text: "Animate"
            onClicked: {
                lblHello.state = "move";
            }
        }
    }
}
同時進行でアニメーションを扱うには「SequentialAnimation」や「ParentAnimation」を使用します。

SequentialAnimationはこのアイテム内に指定したAnimationをコードの上から下へと順番に実行していきます。このQMLコードではボタンを押すとラベルがmoveステートになり、「右に移動→PauseAnimationで1秒待機(targetの指定は不要)→下に移動」という一連のアニメーションが実行されます。
seaq.qml
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Layouts 1.0
import QtQuick.Controls 1.0

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("SequensialAnimation")

    ColumnLayout{
        Label{
            id: lblHello
            text: "Hello!"
            transitions: [
                Transition {
                    from: "black"
                    to: "red"
                    ColorAnimation {
                        target:lblColor
                        duration: 1000
                    }
                },
                Transition{
                    to: "move"
                    SequentialAnimation{
                        NumberAnimation {
                            target: lblHello
                            property: "x"
                            easing.type: Easing.OutQuad
                            to:200
                            duration:500
                        }
                        PauseAnimation {
                            duration: 1000
                        }
                        NumberAnimation {
                            target: lblHello
                            property: "y"
                            to:200
                            duration:250
                        }
                    }
                }
            ]
        }

        Button{
            text: "Animate"
            onClicked: {
                lblHello.state = "move";
            }
        }
    }
}
ParallelAnimationはアイテム内に指定したすべてのAnimationを同時(並列)に実行します。このコードであれば、先と同じシーケンシャルアニメーションを行いながら、ラベルの大きさが2倍になっていきます。
pal.qml
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Layouts 1.0
import QtQuick.Controls 1.0

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("SequensialAnimation")

    ColumnLayout{
        Label{
            id: lblHello
            text: "Hello!"
            transitions: [
                Transition {
                    from: "black"
                    to: "red"
                    ColorAnimation {
                        target:lblColor
                        duration: 1000
                    }
                },
                Transition{
                    to: "move"
                    ParallelAnimation{
                        NumberAnimation{
                            target: lblHello
                            property: "scale"
                            to: 2.0
                            duration: 1750
                        }
                        SequentialAnimation{
                            NumberAnimation {
                                target: lblHello
                                property: "x"
                                easing.type: Easing.OutQuad
                                to:200
                                duration:500
                            }
                            PauseAnimation {
                                duration: 1000
                            }
                            NumberAnimation {
                                target: lblHello
                                property: "y"
                                to:200
                                duration:250
                            }
                        }
                    }
                }
            ]
        }

        Button{
            text: "Animate"
            onClicked: {
                lblHello.state = "move";
            }
        }
    }
}
Animationアイテムにidを割り当てることで、プログラムからアニメーションを制御することができるようになります。現在のアニメーションの状態を調べるには「running(実行中ならtrue)」「pause(一時停止中ならtrue。完全に停止しているかどうかは[running==false]で調べる)」プロパティを取得します。
manual.qml
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Layouts 1.0
import QtQuick.Controls 1.0

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("SequensialAnimation")

    ColumnLayout{
        Label{
            id: lblHello
            text: "Hello!"
        }

        Button{
            text: "Animate"
            onClicked: {
                // アニメーションの開始。
                // moveanim.running = true; でも実行される
                moveanim.start();

                // stop() - 停止する
                // complete() - 対象のプロパティをアニメーション後の値にして停止
                // pause() - 一時停止
                // resume() - 一時停止を終了して再開
            }

            NumberAnimation {
                id: moveanim
                target: lblHello
                property: "x"
                to: 200
                duration: 1000

                onStarted: {
                    // アニメーション開始のシグナル
                    lblHello.text = "Moving...";
                }
                onStopped: {
                    // アニメーション停止・完了時のシグナル
                    lblHello.text = "Done!";
                }
            }
        }
    }
}
2018/10/30