qml之动画(Animations)

动画被用于属性的改变。一个动画定义了属性值改变的曲线,将一个属性值变化从一个值过渡到另一个值。动画是由一连串的目标属性活动定义的,平缓的曲线算法能够引发一个定义时间内属性的持续变化。所有在QtQuick中的动画都由同一个计时器来控制,因此它们始终都保持同步,这也提高了动画的性能和显示效果。

简单示例

Rectangle {
        id:id_root
        width: 800
        height: 400
        color:"black"
        Rectangle {
            width: 100
            height: 100
            color: "red"
            NumberAnimation on x {
                from: 0
                to: 700
                duration: 4000
                loops: Animation.Infinite
            }
            RotationAnimation on rotation {
                from:0
                to: 360
                duration: 4000
                loops: Animation.Infinite
            }
        }
    }

效果
qml之动画(Animations)

上面这个例子在x坐标和旋转属性上应用了一个简单的动画。每一次动画持续4000毫秒并且永久循环。x轴坐标动画展示了元素的x坐标逐渐移至240,旋转动画展示了当前角度到360度的旋转。两个动画同时运行,并且在加载用户界面完成后开始。

动画元素

有几种类型的动画,每一种都在特定情况下都有最佳的效果,下面列出了一些常用的动画:

PropertyAnimation(属性动画)- 使用属性值改变播放的动画

NumberAnimation(数字动画)- 使用数字改变播放的动画

ColorAnimation(颜色动画)- 使用颜色改变播放的动画

RotationAnimation(旋转动画)- 使用旋转改变播放的动画

除了上面这些基本和通常使用的动画元素,QtQuick还提供了一切特殊场景下使用的动画:

PauseAnimation(停止动画)- 运行暂停一个动画

SequentialAnimation(顺序动画)- 允许动画有序播放

ParallelAnimation(并行动画)- 允许动画同时播放

AnchorAnimation(锚定动画)- 使用锚定改变播放的动画

ParentAnimation(父元素动画)- 使用父对象改变播放的动画

SmotthedAnimation(平滑动画)- 跟踪一个平滑值播放的动画

SpringAnimation(弹簧动画)- 跟踪一个弹簧变换的值播放的动画

PathAnimation(路径动画)- 跟踪一个元素对象的路径的动画

Vector3dAnimation(3D容器动画)- 使用QVector3d值改变播放的动画

当使用更加复杂的动画时,我们可能需要在播放一个动画时中改变一个属性或者运行一个脚本。对于这个问题,QtQuick提供了一个动作元素:

PropertyAction(属性动作)- 在播放动画时改变属性

ScriptAction(脚本动作)- 在播放动画时运行脚本

应用动画

动画可以通过以下几种方式来应用:

属性动画 - 在元素完整加载后自动运行

属性动作 - 当属性值改变时自动运行

独立运行动画 - 使用start()函数明确指定运行或者running属性被设置为true(比如通过属性绑定)

为了演示动画的使用方法,我写了个CClickRectangle自定义组件。

CClickRectangle.qml:

//CClickRectangle.qml

import QtQuick 2.0

Item {
    id: root
    width: container.childrenRect.width
    height: container.childrenRect.height
    property alias text: label.text
    property alias color: id_rect.color
    signal clicked

    Column {
        id: container
        Rectangle{
            id:id_rect
            border.width: 8
            border.color: "white"
            width: 60
            height: 60
        }
        Text {
            id: label
            width: id_rect.width
            horizontalAlignment: Text.AlignHCenter
            wrapMode: Text.WordWrap
            color: "white"
        }
    }

    MouseArea {
        anchors.fill: parent
        onClicked: root.clicked()
    }
}

调用示例

import QtQuick 2.0
import QtQuick.Window 2.2

Window {
    id:mainRoot
    visible: true
    width: 600
    height: 600
    Rectangle {
        id:id_root
        anchors.fill: parent
        color:"black"
        //Animation on
        CClickRectangle{
            id:id_r1
            text: "Animation on"
            color: "green"
            x:50
            y:500
            NumberAnimation on y {
                to: 0; duration: 4000
            }
            onClicked: y = 500
        }
        //behavior on
        CClickRectangle{
            id:id_r2
            text: "behavior on"
            color: "blue"
            x:250
            y:500
            Behavior on y {
                NumberAnimation { duration: 4000 }
            }
            onClicked: y = 0
        }
        //standalone animation
        CClickRectangle{
            id:id_r3
            text: "standalone animation"
            color: "red"
            x:450
            y:500
            NumberAnimation {
                id: anim
                target: id_r3
                properties: "y"
                from: 500
                to: 0
                duration: 4000
            }
            onClicked: anim.start()
        }
    }
}

三个火箭位于相同的y轴坐标(y = 500)。它们都需要移动到y = 0。每一个火箭都使用了一种方法来完成这个功能,如图:
qml之动画(Animations)

Animation on:

CClickRectangle{
     id:id_r1
     text: "Animation on"
     color: "green"
     x:50
     y:500
     NumberAnimation on y {
         to: 0; duration: 4000
     }
     onClicked: y = 500
 }

第一火箭使用了Animation on 属性变化的策略来完成。动画会在加载完成后立即播放。点击火箭可以重置它回到开始的位置。在动画播放时重置第一个火箭不会有任何影响。在动画开始前的几分之一秒设置一个新的y轴坐标让人感觉挺不安全的,应当避免这样的属性值竞争的变化。

behavior on:

CClickRectangle{
     id:id_r2
     text: "behavior on"
     color: "blue"
     x:250
     y:500
     Behavior on y {
         NumberAnimation { duration: 4000 }
     }
     onClicked: y = 0
}

第二个火箭使用了behavior on 属性行为策略的动画。这个行为告诉属性值每时每刻都在变化,通过动画的方式来改变这个值。可以使用行为元素的enabled : false来设置行为失效。当你点击这个火箭时它将会开始运行(y轴坐标逐渐移至0)。

standalone animation:

CClickRectangle{
     id:id_r3
     text: "standalone animation"
     color: "red"
     x:450
     y:500
     NumberAnimation {
          id: anim
          target: id_r3
          properties: "y"
          from: 500
          to: 0
          duration: 4000
      }
    onClicked: anim.start()
    }

第三个火箭使用standalone animation独立动画策略。这个动画由一个私有的元素定义并且可以写在文档的任何地方。点击火箭调用动画函数start()来启动动画。每一个动画都有start(),stop(),resume(),restart()函数。这个动画自身可以比其他类型的动画更早的获取到更多的相关信息。我们只需要定义目标和目标元素的属性需要怎样改变的一个动画。我们定义一个to属性的值,在这个例子中我们也定义了一个from属性的值允许动画可以重复运行。

效果如图:
qml之动画(Animations)

注意
另一个启动/停止一个动画的方法是绑定一个动画的running属性。当需要用户输入控制属性时这种方法非常有用:

NumberAnimation {
        ...
        // animation runs when mouse is pressed
        running: area.pressed
    }
    MouseArea {
        id: area
    }

动画分组

通常使用的动画比一个属性的动画更加复杂。例如你想同时运行几个动画并把他们连接起来,或者在一个一个的运行,或者在两个动画之间执行一个脚本。动画分组提供了很好的帮助,作为命名建议可以叫做一组动画。有两种方法来分组:平行与连续。你可以使用SequentialAnimation(连续动画)和ParallelAnimation(平行动画)来实现它们,它们作为动画的容器来包含其它的动画元素。

SequentialAnimation:同一时间只能执行一个动画,当前动画完成后再执行下一个动画。
ParallelAnimation:多个动画可以同时进行。

SequentialAnimation:

import QtQuick 2.0
import QtQuick.Window 2.2

Window {
    id:mainRoot
    visible: true
    width: 600
    height: 600
    Rectangle {
        id:id_root
        anchors.fill: parent
        color:"black"
        CClickRectangle{
            id:id_r1
            text: "Animation on"
            color: "green"
            x:0
            y:0
            onClicked: anim.restart()
        }
        SequentialAnimation {
                id: anim
                NumberAnimation {
                    target: id_r1
                    properties: "y"
                    to: 500
                    duration: 4000
                }
                NumberAnimation {
                    target: id_r2
                    properties: "x"
                    to: 500
                    duration: 4000
                }
            }
    }
}

该动画演示了火箭先移动y坐标至y = 500处,然后再移动x坐标至x = 500处

ParallelAnimation:

import QtQuick 2.0
import QtQuick.Window 2.2

Window {
    id:mainRoot
    visible: true
    width: 600
    height: 600
    Rectangle {
        id:id_root
        anchors.fill: parent
        color:"black"
        CClickRectangle{
            id:id_r1
            text: "Animation on"
            color: "green"
            x:0
            y:0
            onClicked: anim.restart()
        }
        ParallelAnimation  {
                id: anim
                NumberAnimation {
                    target: id_r1
                    properties: "y"
                    to: 500
                    duration: 4000
                }
                NumberAnimation {
                    target: id_r2
                    properties: "x"
                    to: 500
                    duration: 4000
                }
            }
    }
}

该动画演示了动画id_r1和id_r2同时执行。

上一篇:比特币涨幅已超过1000%,还能持续上涨么?


下一篇:matlab练习程序(GPU加速)