前言
使用QML差不多2年了,在使用過程中深深的感受到QML的強大與便捷,讓我深陷其中,不能自拔。其中QML相比傳統的界面最大的優勢就是便捷的動畫效果與炫酷的粒子效果,讓QML做出來的界面能媲美WPF和各種JS前端框架的效果。下面我們就開始進入QML動畫美妙的世界吧。
更現代的程序界面
與傳統的界面相比,現代化的程序界面的特色是更加鮮艷的色彩,以及更加豐富的動畫。QML設計的目的就是用來創建Fluid UIs(流體界面),所謂流體界面,就是UI組件是動態的,而不會突然出現、消失或跳轉,QML的動畫效果就很好的實現了流體界面的要求。
QML動畫實現方法
在QML中,實現動畫最常用的是State(狀態)&Transactions(過渡) 與 Animating Properyty Changes(屬性改變動畫)這兩種方法。
1、State & Transactions(狀態與過渡)
QML可以在組件中聲明各種State(狀態),在狀態中可以包含該組件所需修改的屬性值,當我們想改變組件的屬性值時,只需該組件的State即可。Transaction(過渡)用來設置狀態改變時的動畫,常與State配合使用。創建一個Transaction對象,然后將其添加到組件的transcation屬性中。使用方法如下:
以下代碼展示的是使用State&Transactions方法實現一個頁面切換的動畫效果。
Window { visible: true width: 400; height: 300 title: "Animation" Rectangle { anchors.fill: parent; color: "green" } Rectangle { id: pageA color: "red" width: parent.width; height: parent.height // 創建2個狀態"show","hide"分別表示顯示界面和隱藏界面 states: [ // 將PageA的屬性y賦值為0,opacity賦值為1以實現顯示的效果 State { name: "show"; PropertyChanges { target: pageA; y: 0; opacity: 1 } }, // 將PageA的屬性y賦值為-height,opaticy賦值為0以實現窗口向上移動並消失的效果 State { name: "hide"; PropertyChanges { target: pageA; y: -height; opacity: 0 } } ] state: "show" transitions: Transition { PropertyAnimation { properties: "y,opacity"; duration: 1000; easing.type: Easing.InOutBack } } } } MouseArea { anchors.fill: parent onClicked: { if(pageA.state == "show") pageA.state = "hide" else pageA.state = "show" } } }
當pageA的狀態由”show”改變為”hide”時,PropertyChanges{target:pageA;y:-height;opacity:0}執行,將屬性y改為-height,opacity改為0。
當屬性改變時,PropertyAnimation{properties:"y,opacity";duration:1000;easing.type:Easing.InOutBack}被執行,產生動畫效果。
2、Animating Property Changes(屬性改變動畫)
在屬性上使用Behaviors(行為)關鍵字,指定在該屬性改變時使用動畫。修改以上代碼使用Behaviors實現相同的效果。
Window { visible: true width: 400 height: 300 title: qsTr("Animation") Rectangle { id: pageB color: "green" anchors.fill: parent } Rectangle { id: pageA color: "red" width: parent.width height: parent.height // 給y屬性改變安裝動畫 Behavior on y { PropertyAnimation { duration: 1000; easing.type: Easing.InOutBack } } // 給opacity屬性改變安裝動畫 Behavior on opacity { PropertyAnimation{ duration: 1000 } } } MouseArea { anchors.fill: parent onClicked: { if (pageA.y == 0) { pageA.y = -pageA.height pageA.opacity = 0 } else { pageA.y = 0 pageA.opacity = 1 } } }
有些情況下還可以通過enabled屬性來停用Behavior。注意這里的PropertyAnimation的from和to屬性是不需要定義的,因為這些值已經提供了,分別是Rectangle的當前值和onClicked處理器中設置的新值。
3、其他動畫使用方法
3.1 動畫作為屬性值的來源
一個動畫被應用為屬性值的源(property value source),要使用“動畫on屬性”語法。
Window { visible: true width: 400 height: 300 title: qsTr("Animation") Rectangle { id: pageB color: "green" anchors.fill: parent } Rectangle { width: 100; height: 100 color: "red" //啟動后開始動畫 PropertyAnimation on x {to: 50; duration: 1000; loops: Animation.Infinite} PropertyAnimation on y {to: 50; duration: 1000; loops: Animation.Infinite} } }
3.2 在信號處理器中創建一個動畫,並在接收到信號時觸發
Window { visible: true width: 400 height: 300 title: qsTr("Animation") Rectangle { id: pageB color: "green" anchors.fill: parent } Rectangle { id: rect width: 100; height: 100 color: "red" MouseArea { anchors.fill: parent onClicked: PropertyAnimation { target: rect properties: "x,y" to: 50 duration: 1000 } } } }
因為動畫沒有綁定到一個特定的對象或者屬性,所以必須指定target和property(或者targets和properties)屬性的值。而且還需要使用to屬性來指定新的x和y的值。
3.3 獨立動畫
動畫也可以像一個普通的QML對象一樣進行創建,而不需要綁定到任何特定的對象和屬性。
Window { visible: true width: 400 height: 300 title: qsTr("Animation") Rectangle { id: pageB color: "green" anchors.fill: parent } Rectangle { id: rect width: 100; height: 100 color: "red" PropertyAnimation { id: animation duration: 1000 } MouseArea { anchors.fill: parent onClicked: { animation.target = rect animation.properties = "x,y" animation.to = 50 animation.start() } } } }
一個獨立的動畫對象默認是沒有運行的,必須使用running屬性或者start()和stop()函數來明確地運行它。因為動畫沒有綁定到一個特殊得對象或屬性上,所以必須定義target和property(或者targets和properties)屬性的值。也需要用to屬性來指定新的x和y值。對於動畫在不是一對一對象屬性進行動畫而且動畫需要明確開始和停止的情況下是非常有用的。
動畫元素
所有的動畫都繼承自Animation元素,盡管無法直接創建Animation對象,不過它為動畫元素提供了必要的屬性和函數。它允許使用running屬性和start()和stop()函數來控制動畫的開始和停止,也可以通過loops屬性定義動畫的循環次數。
PropertyAnimation是用來為屬性提供動畫的最基本的動畫元素,可以用來為real、int、color、rect、point、size和vector3d等屬性設置動畫,被NumberAnimation、colorAnimation、RotationAnimation和Vector3dAnimation等元素繼承。NumberAnimation對real和int屬性提供了更高效的實現;Vector3dAnimation對vector3d屬性提供了更高效的支持;而ColorAnimation和RotationAnimation分別對color和rotation屬性變化動畫提供了特定的屬性支持。
1. ColorAnimation允許顏色值設置from和to屬性。
Rectangle { id: rect width: 100; height: 100 color: "green" // 啟動運行,由綠色變為紅色 ColorAnimation on color { from: "green"; to: "red"; duration: 1000 } }
2. RotationAnimation允許設定旋轉的方向。
Rectangle { id: rect width: 100; height: 100 color: "red" anchors.centerIn: parent // 啟動運行,順時針旋轉90° RotationAnimation on rotation { to: 90; duration: 1000; direction: RotationAnimation.Clockwise } }
3. SmoothedAnimation: 它是一個專門的NumberAnimation,當目標值改變時在動畫中為其提供了一個平滑的變化;
4. SpringAnimation: 提供了一個像彈簧一樣的動畫,可以設置mass、damping和epsilon等屬性
5. ParentAnimation: 用來在改變父項目時產生動畫(對應ParentChange元素)
6. AchorAnimation: 用來在改變錨時產生動畫(對應AnchorChanges元素)
對於任何基於PropertyAnimation的動畫都可以通過設置easing屬性來控制在屬性值動畫中使用的緩和曲線。它們可以影響這些屬性值的動畫效果,提供一些如反彈、加速和減速等視覺效果。OutBounce來創建一個動畫到達目標值時的反彈效果。
組合動畫
多個動畫可以組合成一個單一的動畫,這可以使用ParallelAnimation或者SequentialAnimation動畫組元素中的一個實現。在ParallelAnimation中的動畫會同時進行,而在SequentialAnimation中的動畫會一個個地運行。想要運行多個動畫,可以在一個動畫組中定義。以下代碼分別表示串行動畫和並行動畫。
Window { visible: true width: 400 height: 300 title: qsTr("Animation") Rectangle { id: pageB color: "green" anchors.fill: parent } Rectangle { id: rect width: 100 height: 100 color: "red" // 串行動畫 SequentialAnimation { id: animation // NumberAnimation { target: rect properties: "x,y" to: 50 duration: 1000 } ColorAnimation { target: rect properties: "color" to: "blue" duration: 1000 } } MouseArea { anchors.fill: parent onClicked: animation.start() } } }
Window { visible: true width: 400 height: 300 title: qsTr("Animation") Rectangle { id: pageB color: "green" anchors.fill: parent } Rectangle { id: rect width: 100 height: 100 color: "red" // 串行動畫 ParallelAnimation { id: animation // NumberAnimation { target: rect properties: "x,y" to: 50 duration: 1000 } ColorAnimation { target: rect properties: "color" to: "blue" duration: 1000 } } MouseArea { anchors.fill: parent onClicked: animation.start() } } }
其他動畫元素
QML還為動畫提供了其他一些有用的元素
1. PauseAnimation: 在動畫中間進行暫停
2. ScriptAnimation: 允許在動畫中執行JavaScript,也可以和StateChangeScript一起使用來重用已經存在的腳本