1. 程式人生 > >Qt5官方demo解析集13——Qt Quick Particles Examples - Image Particles

Qt5官方demo解析集13——Qt Quick Particles Examples - Image Particles

tro dem 屬性 white creat running 透明 hit stars

本系列全部文章能夠在這裏查看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"
    }
}


這裏將小熊的sprite圖貼下:
技術分享

Qt5官方demo解析集13——Qt Quick Particles Examples - Image Particles