Qt 6 QML 和訳文書 P115~P144
Advanced Techniques
Performance of QML
QMLのパフォーマンス
QMLとJavascriptはインタープリタ言語です。これは実行する前にコンパイルする必要はないということを意味します。その代わり、実行エンジンの中で実行されています。けれども、解釈はコストがかかる作業なので、いろいろなテクニックがパフォーマンス向上のために利用されています。QMLエンジンはjust-in-timeコンパイルをパフォーマンス改善のために利用しています。再度コンパイルすることを避けるために、中間の出力結果をキャッシュします。これは開発者としてのあなたのために間断なくうごきます。この唯一の足跡は、qmlcとjscで終わるファイルがソースファイルの中で見つかる事です。もしあなたが最初の追跡によって引きおこされる最初のスタートアップの痛みを避けたいのであれば、QMLとJavaScriptをプリコンパイルすることもできます。これはあなたにQtのリソースファイルの中へコードを置くことを要求し、詳細はCompiling QML Ahead of Timeで記述されます。(https://doc.qt.io/qt-6/qtquickdeployment.html#ahead-of-time-compilation)
Qtドキュメンテーション内の章です。
Fluid Elements
今まで、私たちはほとんど単純なグラフィカル図形要素をみてきましたし、それらを整理し、操作する方法を見てきました。この章はそれらをアニメ―とをすることによって、より面白く変化させる方法についてのものになります。アニメーションは現代の、なめらかなユーザーインターフェースのための、主要な基盤の一つであり、あなたのユーザーインターフェースに、状態、遷移そしてアニメーションを通して採用できます。それぞれの状態はプロパティの変化のセットで、状態変化でアニメーションと結びつきます。これらの変化はある状態から別の状態への遷移として記述されます。さらに遷移中に利用されているアニメーションのほかに、それらはいくつかの記述されたイベントによって引き起こされるスタンドアロンな要素として利用することもできます。
Animations
アニメーションはプロパティの変化に応じます。アニメーションはある値から別の値へと、プロパティの値が変化するときの補間曲線を定義します。これらのアニメーションはある値から別の値へ滑らかな遷移を作ります。あるアニメーションはアニメートされる一連のターゲットプロパティ、補間曲線のためにはイージングカーブ(徐行曲線)、そして持続時間により定義されます。Qt Quick内の全てのアニメーションは同じタイマーによって管理され、それゆえ同時進行します。これはアニメーションのパフォーマンスと見た目の質を改善します。
Animations control how properties change using value interpolation
アニメーションはプロパティが補間値を使ってどのように変化するのかを管理する
これは基本的なコンセプトです。QMLは要素、プロパティ、そして記述に基づいています。全ての要素は数十のプロパティを提供し、それぞれのプロパティはあなたにアニメートされるのを待っています。本の中では、これが壮観な競技場であるということがわかります。あなたはいくつかのアニメーションを見て、それらの美しさとあなたの創造的な天才も賞賛していることに気付くでしょう。それから思い出してください。アニメーションはプロパティの変化を管理するものであり、全ての要素には、あなたの自由になる数十のプロパティがあるということを。
力を解放せよ!
// AnimationExample.qml
import QtQuick
Image {
id: root
source: "assets/background.png"
property int padding: 40
property int duration: 4000
property bool running: false
Image {
id: box
x: root.padding;
y: (root.height-height)/2
source: "assets/box_green.png"
NumberAnimation on x {
to: root.width - box.width - root.padding
duration: root.duration
running: root.running
}
RotationAnimation on rotation {
to: 360
duration: root.duration
running: root.running
}
}
MouseArea {
anchors.fill: parent
onClicked: root.running = true
}
}
上の例はxとrotationプロパティで適用される単純なアニメーションを表示します。それぞれのアニメーションは4000ミリセカンドの存続期間を持ちます。x 上のアニメーションは、x 座標をオブジェクトから 240px まで徐々に移動します。回転時のアニメーションは、現在の角度から 360 度まで実行されます。両方のアニメーションは並行して実行され、MouseArea がクリックされたときに開始されます。
Animation Elements
いくつかのタイプのアニメーション要素があり、それぞれは特別なユースケースのために最適化されます。こちらは最も前途有望なアニメーションのリストです。
PropertyAnimation - Animates changes in property values
プロパティの値で変化をアニメ―トします。
NumberAnimation - Animates changes in qreal-type values
qreal型の値の変化をアニメ―とします。
ColorAnimation - Animates changes in color values
color型の値の変化をアニメ―とします。
RotationAnimation - Animates changes in rotation values
回転の値の変化をアニメ―トします。
Besides these basic and widely used animation elements, Qt Quick also provides more specialized animations for specific use cases:
これらの基礎そして広く利用されたアニメーション要素以外にも、Qt Quickはより多くの特別なアニメーションを、特別なユースケースの場合に提供もします。
PauseAnimation - Provides a pause for an animation
アニメーションのためにポーズを提供します。
SequentialAnimation - Allows animations to be run sequentially
アニメーションをシーケンシャルに実行するようにします。
ParallelAnimation - Allows animations to be run in parallel
アニメーションを並行に実行するようにします。
AnchorAnimation - Animates changes in anchor values
アンカー値で変化をアニメ―トします。
ParentAnimation - Animates changes in parent values
親の値で変化をアニメ―トします。
SmoothedAnimation - Allows a property to smoothly track a value
プロパティが値を滑らかに追跡するようにします。
SpringAnimation - Allows a property to track a value in a spring-like motion
プロパティが噴水のような動きで値を追跡するようにします。
PathAnimation - Animates an item alongside a path
パスを添えてアイテムをアニメ―トします。
Vector3dAnimation - Animates changes in QVector3d values
Later we will learn how to create a sequence of animations.
アニメーションのシーケンスの作り方を学びます。
While working on more complex animations, there is sometimes a need to change a property or to run a script during an ongoing animation. For this Qt Quick offers the action elements, which can be used everywhere where the other animation elements can be used:
PropertyAction - Specifies immediate property changes during animation ScriptAction - Defines scripts to be run during an animation
The major animation types will be discussed in this chapter using small, focused examples.
より複雑なアニメーションで動かすために、時々プロパティを変化させたり、実行中のアニメーションの途中でスクリプトを走らせたりする必要があります。この ためにQt Quickはaction要素を提供し、それは他のアニメーション要素を使うことができる場所であればどこでも利用できます。
プロパティアクション-アニメーション中の即時のプロパティ変化を特定します。
スクリプトアクション-アニメーション中に走らせるスクリプトを定義します。
主なアニメーション型は小さな、焦点を絞った例を使ってこの章で論じられます。
Applying Animations
アニメーションはいくつかの方法で適用できます。
プロパティ上のアニメーションー完全に読み込まれた後で自動的に実行
プロパティ上の動作ープロパティが変更するときに自動的に実行
スタンドアロンアニメーションーstart()あるいはrunninigがtrueにセットされて、明示的にアニメーションが始まるときに実行
アニメーションが状態遷移のなかでどのように使うことができるのかも後でわかります。
Clickable Image V2
To demonstrate the usage of animations we reuse our ClickableImage component from an earlier chapter and extended it with a text element.
アニメーションの使用を実際に示すため、最初の方の章からClickableImageコンポーネントを再利用し、text elementでそれを拡張します。
// ClickableImageV2.qml
// Simple image which can be clicked
import QtQuick
Item {
id: root
width: container.childrenRect.width
height: container.childrenRect.height
property alias text: label.text
property alias source: image.source
signal clicked
Column {
id: container
Image {
id: image
}
Text {
id: label
width: image.width
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
color: "#ececec"
}
}
MouseArea {
anchors.fill: parent
onClicked: root.clicked()
}
}
To organize the element below the image we used a Column positioner and calculated the width and height based on the column’s childrenRect property. We exposed text and image source properties, and a clicked signal. We also wanted the text to be as wide as the image, and for it to wrap. We achieve the latter by using the Text element's wrapMode property.
イメージの下にある要素を編成するために、Columnポジショナを使いました。そしてカラムのchildrenRectプロパティを元に幅と高さを計算しました。私たちはテキストとイメージのソースプロパティを示し、そしてクリックシグナルを示しました。また、てきすとがイメージと同じくらいの幅であってほしいので、それをラップしました。私たちはText elementのwrapModeプロパティを使うことで後者を達成します。
Parent/child geometry dependency
Due to the inversion of the geometry-dependency (parent geometry depends on child geometry), we can’t set a width / height on the ClickableImageV2, as this will break our width / height binding. You should prefer the child’s geometry to depend on the parent’s geometry if the item is more like a container for other items and should adapt to the parent's geometry.
ジオメトリ逆依存のため(親ジオメトリは子ジオメトリに依存している)私たちは、ClickableImageV2上で幅と高さを設定することができません。これがwidthとheightの連結を壊します。もしアイテムが他のアイテムのためのコンテナのようであり、親のアイテムのジオメトリに適合させるべきであるならば、子のジオメトリを親のジオメトリへ依存させるようにした方がよいです。
The objects ascending
The three objects are all at the same y-position ( y=200 ). They all need to travel to y=40 , each of them using a different method with different sideeffects and features.
First object
The first object travels using the Animation on strategy. The animation starts immediately.
最初のオブジェクトは戦略上アニメーションを使って往復運動をします。アニメーションは即座に始まります。
ClickableImageV2 {
id: greenBox
x: 40; y: root.height-height
source: "assets/box_green.png"
text: qsTr("animation on property")
NumberAnimation on y {
to: 40; duration: 4000
}
}
When an object is clicked, its y-position is reset to the start position, and this applies to all of the objects. On the first object, the reset does not have any effect as long as the animation is running. This can be visually disturbing, as the y-position is set to a new value for a fraction of a second before the animation starts. Such competing property changes should be avoided.
オブジェクトがクリックされると、yの位置は最初の位置へ再セットされ、そしてこれはそのオブジェクトのすべてに適用されます。最初のオブジェクトでは、その再設定はアニメーションが実行している限り効果を全く持ちません。アニメーションが開始されるほんの一瞬前、y 位置が新しい値に設定されるため、これは視覚的に邪魔になる可能性があります。このような競合するプロパティの変更は避ける必要があります。
Second object
The second object travels using a Behavior on animation. This behavior tells the property it should animate each change in value. The behavior can be disabled by setting enabled: false on the Behavior element.
第2のオブジェクトはアニメーション上でBehaviorを利用して動きます。このbehaviorはプロパティに値でそれぞれの変化をアニメートするべきであると伝えます。behaviorはBehavior要素上で、enabled: falseをセットすることによって無効化できます。
ClickableImageV2 {
id: blueBox
x: (root.width-width)/2; y: root.height-height
source: "assets/box_blue.png"
text: qsTr("behavior on property")
Behavior on y {
NumberAnimation { duration: 4000 }
}
onClicked: y = 40
// random y on each click
// onClicked: y = 40 + Math.random() * (205-40)
}
The object will start traveling when you click it (its y-position is then set to 40). Another click has no influence, as the position is already set. You could try to use a random value (e.g. 40 + (Math.random() \* (205- 40) ) for the y-position. You will see that the object will always animate to the new position and adapt its speed to match the 4 seconds to the destination defined by the duration of the animation.
オブジェクトはクリックするときにトラベルをスタートします。(そのyの位置が40にセットされています。)別のクリックは影響を持ちません。位置が既にセットされているからです。あなたはy位置のために、ランダム値を使用してみることもできます。(例えば、40+(Math.random()\*(205-40))。
あなたはオブジェクトが常に新しい位置にアニメートし、そのスピードが、アニメーションの持続時間によって定義された目的へ4秒に一致するようになっていることがわかるでしょう。
Third object
3番目のオブジェクトはスタンドアロンアニメーションを使います。アニメーションはそれ自体の要素として定義され、ドキュメント内のほとんどどこにでもいることができます。
ClickableImageV2 {
id: redBox
x: root.width-width-40; y: root.height-height
source: "assets/box_red.png"
onClicked: anim.start()
// onClicked: anim.restart()
text: qsTr("standalone animation")
NumberAnimation {
id: anim
target: redBox
properties: "y"
to: 40
duration: 4000
}
}
クリックはアニメーションのstart()関数を使ってアニメーションをスタートさせます。それぞれのアニメーションは、start(),stop(),resume()そしてrestart()関数を持ちます。アニメーション自体は、前に見た他のアニメーション型よりもずっと多くの情報を持ちます。私たちがアニメートしたいプロパティの名前にそって、私たちはアニメートされるべき要素である、ターゲットを定義する必要があります。私たちは私たちは一つのto値を定める必要があり、この場合は、一つのfrom値ですが、アニメーションのリスタートをすることができます。
A click on the background will reset all objects to their initial position. The first object cannot be restarted except by re-starting the program which triggers the re-loading of the element.
背景上のクリックが全てのオブジェクトをそれらの初期値へ再設定します。最初のオブジェクトは要素の再読み込みを引き起こすプログラムを再スタートすることによる以外では、再スタートすることができません。
Other ways to control Animations
NumberAnimation {
// [...]
// animation runs when mouse is pressed
running: area.pressed
}
MouseArea {
id: area
}
アニメーションを管理する他の方法
アニメーションをスタートあるいはストップさせる他の方法は、アニメーションの実行プロパティへのプロパティをバインドすることです。これは特にユーザー入力がプロパティの管理にある場合に便利です。
Easing Curves
(徐行曲線?)
アニメーションによってプロパティの値の変化を管理することができます。徐行アトリビュートはプロパティの補間曲線に影響を与えます。今まで私たちが定義した全てのアニメーションは線形補間を使っています。なぜならば、アニメーションの最初の徐行型が、Easing.Linearだからです。小さなプロットで最も良く表示されていて、y軸はアニメートされるプロパティであり、x軸は持続時間です。線形補間はアニメーションのスタートのfrom値から真っ直ぐな線を描き、アニメーションの終わりであるto値へ描きます。だから徐行型は変化の曲線を定義します。徐行型は動いているオブジェクトに対して自然な一致をさぽーとするために慎重に選ばれるべきです。例えば、本のページをめくることに似ていて、ページがスライドされるとき、ページは最初ゆっくりとスライドし、段々テンポを増していき、最後には素早くスライドします。
Animations should not be overused.
UIデザインの他の側面と同様に、アニメーションはUIフローをサポートするために慎重にデザインされるべきであり、それを支配するようにデザインしないようにしてください。目は動くものをとても敏感にとらえ、アニメーションは簡単にユーザーから注意を逸らすことができます。
この例のためのコードはちょっとだけ今までよりも複雑に作られています。私たちは最初に徐行型のグリッドを作り、徐行型によって管理されるBoxを作ります。徐行型はボックスがそのアニメーションのために使う曲線を表示するだけです。ユーザーがボックスが徐行カーブに従ってある方向に動
TIP
EasingTypeの内部は現実の時間でカーブを表示し、興味のある読者は徐行曲線エグザンプルを見ることができます。
// EasingCurves.qml
import QtQuick
import QtQuick.Layouts
Rectangle {
id: root
width: childrenRect.width
height: childrenRect.height
color: '#4a4a4a'
gradient: Gradient {
GradientStop { position: 0.0; color: root.color }
GradientStop { position: 1.0; color: Qt.lighter(root.co
}
ColumnLayout {
Grid {
spacing: 8
columns: 5
EasingType {
easingType: Easing.Linear
title: 'Linear'
onClicked: {
animation.easing.type = easingType
box.toggle = !box.toggle
}
}
EasingType {
easingType: Easing.InExpo
title: "InExpo"
onClicked: {
animation.easing.type = easingType
box.toggle = !box.toggle
}
}
EasingType {
easingType: Easing.OutExpo
title: "OutExpo"
onClicked: {
animation.easing.type = easingType
box.toggle = !box.toggle
}
}
EasingType {
easingType: Easing.InOutExpo
title: "InOutExpo"
onClicked: {
animation.easing.type = easingType
box.toggle = !box.toggle
}
}
EasingType {
easingType: Easing.InOutCubic
title: "InOutCubic"
onClicked: {
animation.easing.type = easingType
box.toggle = !box.toggle
}
}
EasingType {
easingType: Easing.SineCurve
title: "SineCurve"
onClicked: {
animation.easing.type = easingType
box.toggle = !box.toggle
}
}
EasingType {
easingType: Easing.InOutCirc
title: "InOutCirc"
onClicked: {
animation.easing.type = easingType
box.toggle = !box.toggle
}
}
EasingType {
easingType: Easing.InOutElastic
title: "InOutElastic"
onClicked: {
animation.easing.type = easingType
box.toggle = !box.toggle
}
}
EasingType {
easingType: Easing.InOutBack
title: "InOutBack"
onClicked: {
animation.easing.type = easingType
box.toggle = !box.toggle
}
}
EasingType {
easingType: Easing.InOutBounce
title: "InOutBounce"
onClicked: {
animation.easing.type = easingType
box.toggle = !box.toggle
}
}
}
Item {
height: 80
Layout.fillWidth: true
Box {
id: box
property bool toggle
x: toggle ? 20 : root.width - width - 20
anchors.verticalCenter: parent.verticalCenter
gradient: Gradient {
GradientStop { position: 0.0; color: "#2ed5
GradientStop { position: 1.0; color: "#2467
}
Behavior on x {
NumberAnimation {
id: animation
duration: 500
}
}
}
}
}
}
エグザンプルをやってみてアニメーションの間のスピードの変化を観察してください。いくつかのアニメーションはオブジェクトにとって自然に感じます、そしていくつかはいらいらします。
持続時間と、曲線の型以外に、徐行曲線を調和させることができます。例えば、一般的なPropertyAnimationのタイプ(これからアニメーションが最も継承しています。)は追加的にeasing.amplitude, easing.overshoot, そしてeasing.periodプロパティをさぽーとし、特別な徐行曲線の振る舞いと調和できるようにします。徐行引数が徐行曲線に影響を与えるかどうかをチェックするPropertyAnimationドキュメンテーションから徐行テーブル (http://doc.qt.io/qt-6/qml-qtquick-propertyanimation.html#easingprop)に問い合わせてください。
Choose the right Animation
ユーザーインターフェーのコンテキスト内の要素に対する正しいアニメーションを選ぶことは結果に対して決定的です。アニメーションはUIのフローをサポートするもので、ユーザーをいらだたせるものではないことを覚えておいてください。
Grouped Animations
アニメーションはよく一つのプロパティをアニメートするよりもより複雑になるでしょう。あなたは同時にいくつかのアニメーションを動かしたい、あるいは、次々と、もしくは、二つのアニメーション間のスクリプトを実行したい時さえあります。このために、グループ化されたアニメーションを利用できます。名前が示しているように、アニメーションをグループ分けすることが可能です。グループ分けは二つの方法でできます。並行と配列処理です。あなたはSequentialAnimationかParallelAnimation要素を使うことができ、他のアニメーション要素のためにアニメーションのコンテナとして動きます。これらのグループ化されたアニメーションはそれ自体正確にそれらしく使うことができます。
Parallel animations
並行アニメーション
並行アニメーションの全ての直属の子アニメーションはスタートすると並行に走ります。これは一度に異なるプロパティをアニメートできます。
// ParallelAnimationExample.qml
import QtQuick
BrightSquare {
id: root
property int duration: 3000
property Item ufo: ufo
width: 600
height: 400
Image {
anchors.fill: parent
source: "assets/ufo_background.png"
}
ClickableImageV3 {
id: ufo
x: 20; y: root.height-height
text: qsTr('ufo')
source: "assets/ufo.png"
onClicked: anim.restart()
}
ParallelAnimation {
id: anim
NumberAnimation {
target: ufo
properties: "y"
to: 20
duration: root.duration
}
NumberAnimation {
target: ufo
properties: "x"
to: 160
duration: root.duration
}
}
}
Sequential animations
配列処理アニメーション
配列処理アニメーションは宣言される順番:上から下へ、それぞれの子を走らせます。
// SequentialAnimationExample.qml
import QtQuick
BrightSquare {
id: root
property int duration: 3000
property Item ufo: ufo
width: 600
height: 400
Image {
anchors.fill: parent
source: "assets/ufo_background.png"
}
ClickableImageV3 {
id: ufo
x: 20; y: root.height-height
text: qsTr('rocket')
source: "assets/ufo.png"
onClicked: anim.restart()
}
SequentialAnimation {
id: anim
NumberAnimation {
target: ufo
properties: "y"
to: 20
// 60% of time to travel up
duration: root.duration * 0.6
}
NumberAnimation {
target: ufo
properties: "x"
to: 400
// 40% of time to travel sideways
duration: root.duration * 0.4
}
}
}
Nested animations
ネストされたアニメーション
グループ化されたアニメーションもまたネストできます。例えば、配列処理アニメーションは子のアニメーションとして二つの並列したアニメーションを持つことができます。私たちはこれをサッカーボールエグザンプルで表示できます。その考えは左から右へボールを投げそしてその動作をアニメートすることです。
アニメーションを理解するために、私たちはオブジェクトの統合的な変換を分離する必要があります。私たちはアニメーションがプロパティの変化をアニメートしているのだということを思い出す必要があります。こちらが異なる変換です。
An x-translation from left-to-right ( X1 )
(x1)左から右へxの移動
A y-translation from bottom to top ( Y1 ) followed by a translation from up to down ( Y2 ) with some bouncing
下から上へのy移動(Y1)に続いて、上から下への移動(Y2)がバウンスします
A rotation of 360 degrees over the entire duration of the animation ( ROT1 )
全体のアニメーションの持続時間を超えて360度回転する。
The whole duration of the animation should take three seconds.
全体の持続時間は3秒かかります。
私たちは480の幅、300の高さのルート要素として、空アイテムで始めます。
import QtQuick
Item {
id: root
property int duration: 3000
width: 480
height: 300
// [...]
}
私たちはアニメーションの部分をよりよく同時進行するための参照として、全体のアニメーションの持続時間を定義しました。次のステップは背景を苦ウェルことで、私たちの場合緑と青のグラディエントで2つの矩形です。
Rectangle {
id: sky
width: parent.width
height: 200
gradient: Gradient {
GradientStop { position: 0.0; color: "#0080FF" }
GradientStop { position: 1.0; color: "#66CCFF" }
}
}
Rectangle {
id: ground
anchors.top: sky.bottom
anchors.bottom: root.bottom
width: parent.width
gradient: Gradient {
GradientStop { position: 0.0; color: "#00FF00" }
GradientStop { position: 1.0; color: "#00803F" }
}
}
上の青い矩形は200ピクセルの高さで下の一つは空のそこにアンカーsれており、ルート要素の底にあります。
サッカーボールをグリーンに持ってきましょう。ボールはイメージで、"assets/soccer_ball.png"のところに格納されています。はじめに、左の下隅、角の近くに、それを置きたいとします。
Image {
id: ball
x: 0; y: root.height-height
source: "assets/soccer_ball.png"
MouseArea {
anchors.fill: parent
onClicked: {
ball.x = 0
ball.y = root.height-ball.height
ball.rotation = 0
anim.restart()
}
}
}
イメージにはマウスエリアを取り付けておきます。もしボールがクリックされると、ボールの位置が再設定し、アニメーションがスタートします。
SequentialAnimation {
id: anim
NumberAnimation {
target: ball
properties: "y"
to: 20
duration: root.duration * 0.4
}
NumberAnimation {
target: ball
properties: "y"
to: 240
duration: root.duration * 0.6
}
}
これは全体のアニメーション持続時間の40%が上昇のアニメーションで、60%が下降のあにめーしょんです。シーケンスで、各アニメーションが順番に実行されることを指定します。変換は線形パス上でアニメートされますが、全く現在は曲がりません。カーブは徐行曲線を使った後に加えられます。次に、私たちはx軸方向の移動を加える必要があります。x軸方向の移動は、y軸方向に並行して走り、
曲線はイージング曲線を使用して後で追加されますが、現時点では変換のアニメーション化に集中しています。次に、x-翻訳を追加する必要があります。x-trans は y -平行移動と並行して実行されるため、y-translations のシーケンスを x トランスレーションとともに並列アニメーションにカプセル化する必要があります。
ParallelAnimation {
id: anim
SequentialAnimation {
// ... our Y1, Y2 animation
}
NumberAnimation { // X1 animation
target: ball
properties: "x"
to: 400
duration: root.duration
}
}
最後に、ボールが回転しているようにしてみたい。このためには、パラレルアニメーションにもう一つのアニメーションを加える必要があります。RotationAnimationを、回転のために特化されているので、RotationAnimationを選択します。
ParallelAnimation {
id: anim
SequentialAnimation {
// ... our Y1, Y2 animation
}
NumberAnimation { // X1 animation
// X1 animation
}
RotationAnimation {
target: ball
properties: "rotation"
to: 720
duration: root.duration
}
}
それがアニメーションシーケンス全体です。残っていることの1つは、ボールの動きに正しいイージングカーブを提供することです。Y1 アニメーションでは、円運動のように見えるはずなので、Easing.OutCirc 曲線を使用します。Y2は、ボールにバウンドを与えるためにEasing.OutBounceを使用して強化され、バウンドは最後に発生するはずです(Easing.InBounceで試すと、バウンスがすぐに開始されることがわかります)。X1 と ROT1 のアニメーションはそのまま残され、線形曲線になります。参考までに最終的なアニメーションコードは次のとおりです。
ParallelAnimation {
id: anim
SequentialAnimation {
NumberAnimation {
target: ball
properties: "y"
to: 20
duration: root.duration * 0.4
easing.type: Easing.OutCirc
}
NumberAnimation {
target: ball
properties: "y"
to: root.height-ball.height
duration: root.duration * 0.6
easing.type: Easing.OutBounce
}
}
NumberAnimation {
target: ball
properties: "x"
to: root.width-ball.width
duration: root.duration
}
RotationAnimation {
target: ball
properties: "rotation"
to: 720
duration: root.duration
}
}