前言
上一篇文章介绍了QML中简单动画的实现方法,但是通常使用的动画比一个属性的动画更加复杂。例如你想同时运行几个动画并把它们连接起来,或者一个一个的运行,或者在两个动画之间执行一个脚本。动画分组提供了很好的帮助,有两种方法来分组:平行与连续。你可以使用SequentialAnimation(连续动画)和ParallelAnimation(平行动画)来实现它们,它们作为动画的容器来包含其它的动画元素。
平行动画
当平行动画开始时,平行元素的所有子动画都会平行运行,它允许你在同一时间使用不同的属性来播放动画。
来看一个简单的例子,一个斜着往上飞的火箭:
//parallelanimation.qml
import QtQuick 2.3
import QtQuick.Window 2.2
Window {
id: root
visible: true
width: 640
height: 480
property int duration: 3000
ClickableImage {
id: rocket
x: 20; y: 350
source: "image/rocket.png"
onClicked: anim.restart()
}
ParallelAnimation {
id: anim
NumberAnimation {
target: rocket
properties: "y"
to: 20
duration: root.duration
}
NumberAnimation {
target: rocket
properties: "x"
to: 400
duration: root.duration
}
}
}
运行效果:
连续动画
一个连续的动画将会一个一个的运行子动画。
还是以火箭升空为例,不过这次我们先让火箭垂直移动,移动到顶点以后,再水平移动一段距离。
并且垂直移动和水平移动的时间比例为6:4。
//sequentialanimation.qml
import QtQuick 2.3
import QtQuick.Window 2.2
Window {
id: root
visible: true
width: 640
height: 480
property int duration: 3000
ClickableImage {
id: rocket
x: 20; y: 350
source: "image/rocket.png"
onClicked: anim.restart()
}
SequentialAnimation {
id: anim
NumberAnimation {
target: rocket
properties: "y"
to: 20
duration: root.duration * 0.6
}
NumberAnimation {
target: rocket
properties: "x"
to: 400
duration: root.duration * 0.4
}
}
}
运行效果:
嵌套的分组动画
分组动画也是可以嵌套的,例如一个连续动画可以拥有两个平行动画作为子动画。下面我们以一个弹跳滚动的蓝球为例,来看看该如何实现分组动画的嵌套。
import QtQuick 2.3
import QtQuick.Window 2.2
Window {
id: root
visible: true
width: 640
height: 480
property int duration: 3000
Image {
id: background
source: "image/background.jpg"
anchors.fill: parent
}
Image {
id: ball
x: 20; y: 350
source: "image/basketball.png"
MouseArea {
anchors.fill: parent
onClicked: {
ball.x = 20;
ball.y = 240;
anim.restart()
}
}
}
ParallelAnimation {
id: anim
SequentialAnimation {
NumberAnimation {
target: ball
properties: "y"
to: 20
duration: root.duration * 0.2
easing.type: Easing.OutCirc
}
NumberAnimation {
target: ball
properties: "y"
to: 350
duration: root.duration * 0.8
easing.type: Easing.OutBounce
}
}
NumberAnimation {
target: ball
properties: "x"
to: 400
duration: root.duration
}
RotationAnimation {
target: ball
properties: "rotation"
to: 720
duration: root.duration * 1.1
}
}
}
运行效果如下:
下面我们对上面的代码进行详细的解释:
- 首先我们使用了两个Image元素,一个用来当做背景,一个用来放置篮球,并且篮球的图片时间了鼠标点击响应,点击篮球以后,球会回到初始状态并重新开始运行动画。
- 然后我们使用了一个平行动画ParallelAnimation,在该平行动画中,我们先使用了一个连续动画SequentialAnimation来实现篮球的两次y轴的变换。在动画的前20%时间内完成了上升过程,在后80%时间内完成了篮球的下降过程及弹跳实现。
- 因为x轴坐标变换需要与y轴坐标变换同时进行,所以我们需要将y轴坐标变换的连续动画和x轴坐标变换一起压缩进一个平行动画中。
- 然后我们想要让篮球旋转,因此我们向平行动画中添加了一个新的动画,并使用RotationAnima来实现旋转。
- 当我们完成了整个动画链表以后,我们需要给动画提供一个正确的缓冲曲线来过渡球的每个运动过程。我们分别使用了Easing.OutCric和Easing.OutBounce缓冲曲线,前者看上去像是圆周运动,后者让球碰到地面以后会发生反弹。x轴运动和旋转都使用默认的线性曲线。