Qt5官方demo解析集13——Qt Quick Particles Examples - Image Particles
本系列全部文章能夠在這裏查看http://blog.csdn.net/cloud_castle/article/category/2123873
接上文 Qt5官方demo解析集12——Qt Quick Particles Examples - CustomParticles
先嘮下嗑,在上文CustomParticles中我們接觸了強大的ShaderEffect,筆者對其產生了極大的興趣,於是去找了找有沒有很多其它相關的例程,於是就發現了一個QML Video Shader Effects Example。確實效果華麗,以下放個圖,回頭再看看這個demo~
這個demo能夠處理圖片、視頻以及攝像頭數據,算是很強大的功能了。
只是在手機上執行時布局似乎有些問題。
好了,不扯遠了,這次的demo又回歸了ImageParticle。相信大家都不陌生了。這個demo應該比上一個要輕松,我們來看看吧:
依然是熟悉的選擇框:
(1)All at once
這個樣例演示了一群旋轉的小熊。以下有一行話,“QML這麽叼你敢信嗎...”
確實是五彩繽紛哈,怎麽來形成多彩的效果呢?可能你立即會想到ImageParticle中的colorVariation這個屬性,將這個值設高不就能形成多彩的效果嗎?確實不錯,可是假設我們要求這個小熊僅僅在幾種顏色之間變化呢?比如橘紅,紅色。青色,綠色,和黃色?或者再多一點,連隨機數取值也不好做?那麽ImageParticle為我們提供了一個屬性colorTable。這個屬性使得我們能夠在一個一維紋理中取出顏色值賦予圖像。我們通過自己定義一個合適的一維圖像就能夠決定小熊的顏色了。
這裏我將colorVariation設置為1,能夠看下對照效果:
能夠看到顏色確實更加豐富。但因為本身的一維圖像是帶有透明度的,想要模仿原例的效果,我們還須要設置透明度:
這裏將alpha設置為0.5:
好了。代碼非常easy,說了這麽多,就不講了哈。allatonce.qml:
import QtQuick 2.0 import QtQuick.Particles 2.0 Rectangle { color: "white" width: 640 height: 480 ParticleSystem { id: sys } ImageParticle { // ![0] sprites: [ Sprite { name: "bear" source: "qrc:/images/bear_tiles.png" frameCount: 13 frameDuration: 120 } ] colorVariation: 0.5 rotationVelocityVariation: 360 colorTable: "qrc:/images/colortable.png" // ![0] system: sys } Friction { factor: 0.1 system: sys } Emitter { system: sys anchors.centerIn: parent id: particles emitRate: 200 lifeSpan: 6000 velocity: AngleDirection {angleVariation: 360; magnitude: 80; magnitudeVariation: 40} size: 60 endSize: 120 } Text { x: 16 y: 16 text: "QML..." style: Text.Outline; styleColor: "#AAAAAA" font.pixelSize: 32 } Text { anchors.bottom: parent.bottom anchors.right: parent.right anchors.margins: 16 text: "... can you be trusted with the power?" style: Text.Outline; styleColor: "#AAAAAA" font.pixelSize: width > 400 ? 32 : 16 } }
我將colortable的圖貼在以下:
“” < - 就在這裏。它縱向僅僅有一個像素。非常窄。
(2)Colored
這個樣例展示了兩種星星的效果。
colored.qml:
import QtQuick 2.0 import QtQuick.Particles 2.0 Rectangle { width: 360 height: 540 color: "black" ParticleSystem { anchors.fill: parent ImageParticle { // 背景星星 groups: ["stars"] anchors.fill: parent source: "qrc:///particleresources/star.png" } Emitter { group: "stars" emitRate: 800 lifeSpan: 2400 size: 24 sizeVariation: 8 anchors.fill: parent // 布滿父對象的背景星星 } // ![0] ImageParticle { // 未定義的group默覺得"" anchors.fill: parent source: "qrc:///particleresources/star.png" alpha: 0 alphaVariation: 0.2 // 多彩與透明效果 colorVariation: 1.0 } // ![0] Emitter { // 默認發射group名為""的粒子 anchors.centerIn: parent emitRate: 400 lifeSpan: 2400 size: 48 sizeVariation: 8 velocity: AngleDirection {angleVariation: 180; magnitude: 60} // 180的變化度,即是(-180,180) } Turbulence { // 最後加入一些氣流效果 anchors.fill: parent strength: 2 } } }
(3)Color Table
從名字能夠知道這裏樣例著重介紹了colorTable這個屬性。
能夠看到3個光束以類似∞的軌跡執行,colortable.qml:
Rectangle { id: root width: 360 height: 540 color: "black" ParticleSystem { id: particles } ImageParticle { system: particles colorVariation: 0.5 alpha: 0 //! [0] source: "qrc:///particleresources/glowdot.png" colorTable: "qrc:/images/colortable.png" // 這個與樣例一同樣 sizeTable: "qrc:/images/colortable.png" // 有意思的是,我們能夠使用這個一維圖像的透明度來決定粒子的尺寸,依據Manual所說,這個屬性將在之後被移除。取而代之的是使用自己定義的緩和曲線 //! [0] } Emitter { system: particles emitRate: 500 lifeSpan: 2000 y: root.height / 2 + Math.sin(t * 2) * root.height * 0.3 // 定義了一個相似∞的軌跡,刪掉t中的2。它將變成一個橢圓 x: root.width / 2 + Math.cos(t) * root.width * 0.3 property real t; NumberAnimation on t { from: 0; to: Math.PI * 2; duration: 10000; loops: Animation.Infinite } velocityFromMovement: 20 velocity: PointDirection { xVariation: 5; yVariation: 5;} // 有一定的四周消散能力 acceleration: PointDirection { xVariation: 5; yVariation: 5;} size: 16 //endSize: 8 //sizeVariation: 8 } }關於為什麽會形成3個光束:這裏的粒子實際上是按軌跡不斷生成的,新的粒子產生,舊的粒子還未消散。形成了一條光束。而這些粒子隨著生命周期的變化,其顏色、透明度以及尺寸都是與這個colortable一維圖像相關的,這個圖像我在上面貼出來了,當中間幾段有非常明顯的透明區域,當粒子達到與之相相應的生命周期,我們也就看不到了,隨著生命周期的推進,它們又以其它的顏色展現出來。
(4)Deformation
這一節主要介紹了ImageParticle的變形。主要是旋轉以及伸縮。上面兩排海星星在旋轉,以下的海星星被壓縮。
deformation.qml:
import QtQuick 2.0 import QtQuick.Particles 2.0 Rectangle { color: "goldenrod" width: 400 height: 400 ParticleSystem {id:sys} //! [spin] ImageParticle { system: sys groups: ["goingLeft", "goingRight"] source: "qrc:/images/starfish_4.png" rotation: 90 // (順時針)旋轉90度 rotationVelocity: 90 // 旋轉速度 autoRotation: true // 定義該屬性使粒子能依據運動軌跡自己主動旋轉,這裏是平移所以看不到效果 } //! [spin] //! [deform] ImageParticle { system: sys groups: ["goingDown"] source: "qrc:/images/starfish_0.png" // 換了一張圖,這個星星不開心些 rotation: 180 // 旋轉180度,倒過來了 yVector: PointDirection { y: 0.5; yVariation: 0.25; xVariation: 0.25; } // yVector參數是一個矢量,也就是說我們不僅能夠壓縮這個圖像,還能使它隨意拉伸(想象我們拉住一個四邊形的兩個角隨意拉扯的效果)。 } //! [deform] Timer { running: true // 幾個定時器用來發射粒子 repeat: false interval: 100 onTriggered: emitA.enabled = true; } Timer { running: true repeat: false interval: 4200 onTriggered: emitB.enabled = true; } Timer { running: true repeat: false interval: 8400 onTriggered: emitC.enabled = true; } Emitter { // 發射器。假設不清楚能夠參考前面的博文 id: emitA x: 0 y: 120 system: sys enabled: false group: "goingRight" velocity: PointDirection { x: 100 } lifeSpan: 4000 emitRate: 1 size: 128 } Emitter { id: emitB x: 400 y: 240 system: sys enabled: false group: "goingLeft" velocity: PointDirection { x: -100 } lifeSpan: 4000 emitRate: 1 size: 128 } Emitter { id: emitC x: 0 y: 360 system: sys enabled: false group: "goingDown" velocity: PointDirection { x: 100 } lifeSpan: 4000 emitRate: 1 size: 128 } }
(5)Rotation
我們在上一節中就接觸到了rotation,在那個裏面rotation用來實現了圖片的旋轉動畫。而這個樣例則主要介紹了它的autoRotation - 自己主動轉向。
先看看效果:
首先是一串從中下向四周發散的海星星,假設屏幕被點擊。這些海星星將按其執行軌跡翻轉,保證對每一個軌跡而言都是正的。
rotation.qml:
import QtQuick 2.0 import QtQuick.Particles 2.0 Rectangle { color: "goldenrod" width: 1000 height: 1000 ParticleSystem {id: sys} ImageParticle { id: up system: sys source: "qrc:/images/starfish_2.png" autoRotation: true // 這個屬性我們前面有談,再形象一點的話,假設海星星做圓周運動,它的腳會始終指向圓心 rotation: -90 // 粒子在自己主動旋轉後會再加上這個旋轉量,那麽就得到了圖中海星星對每一個運動方向都為正的效果 } Emitter { anchors.centerIn: parent system: sys emitRate: 10 size: 200 lifeSpan: 10000 velocity: AngleDirection {angleVariation: 360; magnitudeVariation: 100;} } MouseArea { anchors.fill: parent // 實現鼠標點擊功能 onClicked: { up.autoRotation = !up.autoRotation up.rotation = up.autoRotation ? -90 : 0 } } }
(6)Sharing
由名字我們就行猜出一些端倪,這個樣例向我們展示了怎樣在同一個或是同一類粒子中展示不同的ImageParticle的效果。
同一時候。一個粒子中還可以包括多個ImageParticle中定義的屬性。
因為原例中的文字是白色的。截圖看不太清楚,我把它改成了藍色。只是這並不影響。我們關註的是它的“小花”(粒子)。
能夠看到小花在整個屏幕中都是偏白色,而在我們選中項的高亮中它顯示為黑紅色。而且它是隨著進入的部分而部分變換。這在實際使用中相當經常使用。
另外還有些listView的操作與動畫,但這就不是我們這一節重點啦~
sharing.qml:
// This example shows how to create your own highlight delegate for a ListView // that uses a SpringAnimation to provide custom movement when the // highlight bar is moved between items. import QtQuick 2.0 import QtQuick.Particles 2.0 Rectangle { property real delegateHeight: 65 width: 200; height: 300 gradient: Gradient { GradientStop { position: 0.0; color: "#EEEEFF" } GradientStop { position: 1.0; color: "lightblue" } } // Define a delegate component. A component will be // instantiated for each visible item in the list. Component { // 我們須要為listView的每一個可視項目創建一個組件,定義一個組件就相似定義了一個qml文件。這個文件名稱就是petDelegate.qml,Item是它的根文件夾。組件中定義的可視化對象不會被直接渲染,除非它被其它類型所載入。 id: petDelegate // 在Item外我們僅僅能定義這個id名 Item { // Item作為這個可視化組件的根文件夾 id: wrapper width: 200; height: delegateHeight z: 10 Column { Text {color: "blue"; text: name; font.pixelSize: 18 } // 按列排放的文字 Text {color: "blue"; text: 'Type: ' + type; font.pixelSize: 14 } Text {color: "blue"; text: 'Age: ' + age; font.pixelSize: 14 } } MouseArea { anchors.fill: parent; onClicked: listView.currentIndex = index; } // 被點擊則作為當前對象 // indent the item if it is the current item states: State { name: "Current" // 設置一個當前狀態 when: wrapper.ListView.isCurrentItem PropertyChanges { target: wrapper; x: 20 } // x縮進20 } transitions: Transition { NumberAnimation { properties: "x"; duration: 200 } // 為這個縮進加入一個動畫 } } } // Define a highlight with customized movement between items. Component { // 將高亮顯示框也定義為一個組件 id: highlightBar Rectangle { // Rectangle作為根文件夾 z: 0 width: 200; height: delegateHeight gradient: Gradient { GradientStop { position: 0.0; color: "#99FF99" } GradientStop { position: 1.0; color: "#88FF88" } } y: listView.currentItem.y; // y坐標與當前項目坐標一致 Behavior on y { SpringAnimation { spring: 2; damping: 0.2 } } // 為 y 的改變加入一個彈簧動畫 //! [1] ImageParticle { // 高亮框內的ImageParticle anchors.fill: parent system: particles source: "qrc:/images/flower.png" color: "red" clip: true alpha: 1.0 } //! [1] } } ListView { id: listView width: 200; height: parent.height model: petsModel // 指定模型 delegate: petDelegate // 指定托付對象 focus: true // Set the highlight delegate. Note we must also set highlightFollowsCurrentItem // to false so the highlight delegate can control how the highlight is moved. highlight: highlightBar // 指定highlight托付對象 highlightFollowsCurrentItem: false // 因為我們要實現自己定義的highlight動畫,因此將該屬性設置為false ParticleSystem { id: particles } // ParticleSystem Emitter { // Emitter system: particles anchors.fill: parent emitRate: 0 lifeSpan: 10000 size: 24 sizeVariation: 8 velocity: AngleDirection { angleVariation: 360; magnitude: 3 } maximumEmitted: 10 startTime: 5000 // 這個屬性我們之前接觸過了,它使Emitter被載入使直接顯示5秒後的效果 Timer { running: true; interval: 10; onTriggered: parent.emitRate = 1; } } //! [0] ImageParticle { // 通用粒子,它覆蓋了整個ListView,因此Emitter發射的粒子大部分通過它渲染 anchors.fill: parent // 可是當Emitter發射的粒子在高亮區域中時,它將轉而使用highlight中的ImageParticle system: particles // 因此粒子顏色與透明度都被改變了 source: "qrc:/images/flower.png" // 但因為highlight中的ImageParticle中的rotation未被設置 alpha: 0.1 // 因此粒子將繼續採用此處的rotationVariation: 180 color: "white" // 這也就是ImageParticle中的屬性共享 rotationVariation: 180 z: -1 } //! [0] } ListModel { // 為ListView提供數據 id: petsModel ListElement { name: "Polly" type: "Parrot" age: 12 size: "Small" } ListElement { name: "Penny" type: "Turtle" age: 4 size: "Small" } ListElement { name: "Warren" type: "Rabbit" age: 2 size: "Small" } ListElement { name: "Spot" type: "Dog" age: 9 size: "Medium" } ListElement { name: "Schrödinger" type: "Cat" age: 2 size: "Medium" } ListElement { name: "Joey" type: "Kangaroo" age: 1 size: "Medium" } ListElement { name: "Kimba" type: "Bunny" age: 65 size: "Large" } ListElement { name: "Rover" type: "Dog" age: 5 size: "Large" } ListElement { name: "Tiny" type: "Elephant" age: 15 size: "Large" } } }
(7)Sprites
sprites大家都不陌生了。我們在前面的程序中大量接觸到了這個東西。使用它要比使用GIF節省多得多的性能,而且與粒子系統一同工作,可以創造動態性能相當高的應用程序。
能夠看到以下有僅僅會動的小熊,上方掉落的海星星也在不斷變化著表情。
當下落到小熊附近時,它們將變成萌萌噠的"驚喜"表情。
sprites.qml:
import QtQuick 2.0 import QtQuick.Particles 2.0 Rectangle { color: "lightsteelblue" width: 800 height: 800 id: root SpriteSequence { // 該類型提供了一個機遇sprite的動畫 sprites: Sprite { name: "bear" source: "qrc:/images/bear_tiles.png" // 圖片貼在下方 frameCount: 13 frameDuration: 120 } width: 250 // 定義小熊的位置與層次 height: 250 x: 20 anchors.bottom: parent.bottom anchors.bottomMargin: 20 z:4 } ParticleSystem { id: sys } ImageParticle { anchors.fill: parent id: particles system: sys sprites: [Sprite { // 定義各種狀態的海星星。並等概率相互轉換 name: "happy" source: "qrc:/images/starfish_1.png" frameCount: 1 frameDuration: 260 to: {"happy": 1, "silly": 1, "angry": 1} }, Sprite { name: "angry" source: "qrc:/images/starfish_0.png" frameCount: 1 frameDuration: 260 to: {"happy": 1, "silly": 1, "angry": 1} }, Sprite { name: "silly" source: "qrc:/images/starfish_2.png" frameCount: 1 frameDuration: 260 to: {"happy": 1, "silly": 1, "noticedbear": 0} }, Sprite { // 在通常情況下,"noticedbear"狀態無法達到 name: "noticedbear" source: "qrc:/images/starfish_3.png" frameCount: 1 frameDuration: 2600 }] } Emitter { // 海星星的發射器 system: sys emitRate: 2 lifeSpan: 10000 velocity: AngleDirection {angle: 90; magnitude: 60; angleVariation: 5} acceleration: PointDirection { y: 10 } size: 160 sizeVariation: 40 width: parent.width height: 100 } SpriteGoal { // 最後定義一個SpriteGoal使海星星在運動到矩形的左下部分時跳轉到"noticedbear"狀態 system: sys width: root.width; height: root.height/2; y: root.height/2; goalState:"noticedbear" } }
Qt5官方demo解析集13——Qt Quick Particles Examples - Image Particles