本系列所有文章可以在這里查看[http://blog.csdn.net/cloud_castle/article/category/2123873](http://blog.csdn.net/cloud_castle/article/category/2123873)
接上文?[Qt5官方demo解析集12——Qt Quick Particles Examples - CustomParticles](http://blog.csdn.net/cloud_castle/article/details/34950673)
先嘮下嗑,在上文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:

好了,代碼很簡單,說了這么多,就不講了哈。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"
}
}
~~~
這里將小熊的sprite圖貼下:

- 前言
- 1——Fortune Server/Client
- 2——Multicast Sender/Receiverz
- 3——Broadcast Sender/Receiver
- 4——Blocking Fortune Client
- 5——Threaded Fortune Server
- 5(總結)——Fortune例程的各個實現區別
- 6——Loopback Example
- 7——Analog Clock Example
- 8——Shaped Clock Example
- 9——Analog Clock Window Example
- 10——Qt Quick Particles Examples - Emitters
- 11——Qt Quick Particles Examples - Affectors
- 12——Qt Quick Particles Examples - CustomParticles
- 13——Qt Quick Particles Examples - Image Particles
- 14——Qt Quick Particles Examples - System
- 15——Chapter 1: Creating a New Type
- 16——Chapter 2: Connecting to C++ Methods and Signals
- 17——Chapter 3: Adding Property Bindings
- 18——Chapter 4: Using Custom Property Types
- 19——Chapter 5: Using List Property Types
- 20——Chapter 6: Writing an Extension Plugin
- 21——Extending QML - Adding Types Example
- 22——Extending QML - Object and List Property Types Example
- 23——Extending QML - Inheritance and Coercion Example
- 24——Extending QML - Default Property Example
- 25——Extending QML - Methods Example
- 26——Extending QML - Grouped Properties Example
- 27——Extending QML - Attached Properties Example
- 28——Extending QML - Signal Support Example
- 29——Extending QML - Property Value Source Example
- 30——Extending QML - Binding Example
- 31——StocQt
- 32——Qt Quick Examples - Threading
- 33——Qt Quick Examples - Window and Screen
- 34——Concentric Circles Example
- 35——Music Player
- 36——Wiggly Example
- 37——Vector Deformation