QML設計飄散效果

来源:https://www.cnblogs.com/hiker-blogs/archive/2020/05/09/12860533.html
-Advertisement-
Play Games

1,目標及展示 首先希望實現文字、圖片、控制項等在觸發後,呈現飄散並消失的效果。在QT常式《Qt Quick Particles Examples》是一個海星點擊滑鼠後呈現打散的效果,這個效果和最終需要的略有不同,所以我們在它的基礎上再加上我需要的一些元素,最終實現如下效果。 圖1(gif) 圖6 2 ...


1,目標及展示

首先希望實現文字、圖片、控制項等在觸發後,呈現飄散並消失的效果。在QT常式《Qt Quick Particles Examples》是一個海星點擊滑鼠後呈現打散的效果,這個效果和最終需要的略有不同,所以我們在它的基礎上再加上我需要的一些元素,最終實現如下效果。

圖1(gif)


圖6

2,設計分析

這個項目我們分析可以拆分成兩個部分,第一是背景飄散效果,第二是背景逐漸消失效果,然後將這兩種效果進行組合,就實現最終需要的效果。
首先先實現飄散效果,QT具有非常強大的粒子化效果,並且只需很少的幾行代碼就能實現效果。不過對於初次使用qml語言進行開發的設計人員,需要先瞭解關鍵字的含義和功能,當然我們可以在常式中微調每個關鍵字參數,根據效果變化進行快速瞭解作用,也可以直接通過強大的F1幫助鍵對關鍵字說明文檔進行全面的瞭解。
在我們這些關鍵字有一定認識後,就可以快速進行粒子化設計了。
第二就是逐步消失的效果,這裡的方法就有很多了:方法一可以使用PS技術,找個單側是過渡效果的蒙版圖片,利用動畫效果逐步遮住顯示內容;
方法二可以直接使用qml 中的 LinearGradient:線性過渡的方法來實現,從單側開始讓逐步隱藏,使10%的區域從透明度為0(全透明)過渡到1(不透明)狀態,然後讓這10%的區域逐漸擴大範圍,最終實現背景消失。如果希望過渡區間更加均勻可以把10%改成20%或更大。
還有很多方法可以實現這個效果,從適應性考慮採用的是後者。

3,設計內容

先說下我的開發環境:
qt5.4.2集成的Qt creator 3.4.1版本
首先創建Quick項目,如果自動創建了MainForm.ui.qml,直接刪除就可以了,我們直接在main.qml中開發就可以了。
我們在建粒子系統之前,先建立一個畫布,畫布大小填充父畫布。然後在這個畫布上添加粒子系統的基本元素:ParticleSystem、Emitter、ImageParticle和應用文件import QtQuick.Particles 2.0代碼如下:

import QtQuick 2.4
import QtQuick.Window 2.2
import QtQuick.Particles 2.0

Window {
    width: 800
    height: 320
    visible: true

    Rectangle {
        id: root
        anchors.fill: parent
        color: "#1f1f1f"

        ParticleSystem {
            id: myParticleSystem
        }

        Emitter {
            id: myEmitter
            system: myParticleSystem

            //發射器區域寬和高
            width: 240
            height: parent.height

            //發射頻率每秒500個元素
            emitRate: 500
            //每個元素的生命周期是1000毫秒
            lifeSpan: 1000
            //每個元素的大小是16*16像素
            size: 16
        }

        ImageParticle {
            system: myParticleSystem
            //Qt自帶粒子圖,可以換成自定義圖片
            source: "qrc:///particleresources/fuzzydot.png"
            //粒子圖使用白色
            color: "white"
        }

    }
}

圖2(gif)

這個圖看來只有粒子,我們還需要動態飄動的效果,下麵在粒子發射器中增加如下代碼。

velocity: PointDirection {
	x: 150
}
acceleration: PointDirection {
	x: 12
}

水平向右設置150像素/秒的速度,水平向右添加一個12像素/秒^2的加速。如果我們需要讓他向左發射時,可以讓x:-150,加速設置也是同理,添加一個符號就表示向左加速。如果我們需要向下發射可以y:150,同理向上發射時是y:-150。
這時我們就有了所有粒子向右飄動的界面,但是飄動狀態還比較單調。我們可以給他增加一些差異性的元素,讓元素更豐富。
讓元素在±8*8像素範圍內隨機變化

sizeVariation: 8

在velocity中增加x/y速度的隨機變化

xVariation: 60
yVariation: 20

在acceleration中增加x/y加速度的隨機變化

xVariation: 6
yVariation: 5

到此元素飄動就有了雪花飛舞的感覺了,飄動的層次均勻並且舒服。

現在感覺顏色稍微有點單調,我們可以在ImageParticle中對顏色增加隨機繫數

colorVariation: 0.1

顏色也有一定的波動了,如下圖顯示

圖3

現在我們的任務就是讓發射器一邊發射一邊向右移動,直到移動到界面外,實現飄散的元素飛舞過程。這裡我們可以使用動畫元素,讓發射器在1秒內從窗體的最左邊向右側視窗外移動,實現的代碼如下

NumberAnimation {
	id: myAnimation
	//設定動畫的目標
	target: myEmitter
	//設定改變的屬性是x坐標
	properties: "x"
	//x移動到父視窗的邊沿
	to: root.width
	//在1秒內完成移動
	duration: 1000
}

有了動畫代碼,我們還需要一個觸發這個動畫的事件,另外粒子系統創建後先不要發送,我們演示時通過滑鼠來激活動畫和粒子系統。
在粒子系統ParticleSystem添加如下代碼,讓粒子系統在創建時停止運行。
running: false
然後提那家數據觸發代碼

MouseArea {
	anchors.fill: parent

	//滑鼠點擊測試
	onClicked: {
		//讓myEmitter視窗複位,這樣滑鼠可重覆點擊
		if (myEmitter.x > 0)
		{
			myAnimation.stop()
			myEmitter.x = 0;
		}
			
		//激活粒子系統
		myParticleSystem.restart()
		//激活動畫
		myAnimation.restart()
	}
}

由於每次動畫執行結束後,myEmitter視窗已經在顯示窗體以外了,那麼在點擊時先讓myEmitter視窗回到初始位置,我們就實現了點擊後重覆演示功能。
效果如下

圖4

到這裡我們第一項飄散的效果就完成了,下一步是實現背景元素逐漸消失的特效。
我們後續會用到LinearGradient元素,需要添加引用import QtGraphicalEffects 1.0。我們首先測試文字,添加如下內容。註意添加的位置,qml添加圖層的規則是先建立的(代碼行號偏小的)圖層在底層,後建立的(代碼行號偏大的)圖層在頂層,我們文字需要顯示在飄飛效果的下麵顯示,所以代碼儘量靠前放置。

Text {
	id:myText
	anchors.centerIn: parent
	text: "Hello world!"
	font.bold: true
	font.pixelSize: 120
	font.family: "微軟雅黑"
	visible: false
}

LinearGradient {
	source: myText
	anchors.fill: myText
	start: Qt.point(0, 0)
	end: Qt.point(myText.width, 0)
	gradient: Gradient {
		GradientStop{id: myGradientStart; position: 0.0; color: "#FFFFFFFF"}
		GradientStop{id: myGradientEnd; position: 0.1; color: "#FFFFFFFF"}
	}
}

代碼中Text項目被設置為隱藏。是因為我們下麵的漸變效果已經基於Text進行漸變覆蓋,我們需要顯示的是漸變的內容,Text的內容就不再被需要了,且當漸變被設置為透明時,會顯示背景的內容,這時Text如果顯示出了就不是我們所希望的效果了。
現在文本內容有了,下一步如何讓其逐步消失,我們可以用動畫控制漸變的定位。
圖5
如上圖所示,首先讓定位點myGradientStart在200毫秒內變成無色,然後讓定位點myGradientEnd移動到終點,這個過程同時讓myGradientStart跟隨移動到終點,但是他們之間需要有個時間差,消失邊界才會有個過渡區間。這裡我們可以使用順序動畫、並行動畫來組合完成這個功能。

最終代碼如下

import QtQuick 2.4
import QtQuick.Window 2.2
import QtQuick.Particles 2.0
import QtGraphicalEffects 1.0


Window {
    width: 800
    height: 320
    visible: true

    Rectangle {
        id: root
        anchors.fill: parent
        color: "#1f1f1f"

        Text {
            id:myText
            anchors.centerIn: parent
            text: "Hello world!"
            font.bold: true
            font.pixelSize: 120
            font.family: "微軟雅黑"
            visible: false
        }

        LinearGradient {
            source: myText
            anchors.fill: myText
            start: Qt.point(0, 0)
            end: Qt.point(myText.width, 0)
            gradient: Gradient {
                GradientStop{id: myGradientStart; position: 0.0; color: "#FFFFFFFF"}
                GradientStop{id: myGradientEnd; position: 0.1; color: "#FFFFFFFF"}
            }
        }

        ParticleSystem {
            id: myParticleSystem
            running: false
        }

        Emitter {
            id: myEmitter
            system: myParticleSystem
            anchors.verticalCenter: parent.verticalCenter

            //發射器區域寬和高
            width: 240
            height: 180

            //發射頻率每秒500個元素
            emitRate: 500
            //每個元素的生命周期是1000毫秒
            lifeSpan: 1000
            //每個元素的大小是16*16像素
            size: 16
            //元素可以在±8*8像素範圍內隨機變化
            sizeVariation: 8
            //元素髮射速度設置,使用點方向模式
            velocity: PointDirection {
                //水平方式速度 150像素/秒
                x: 150
                //隨著變數調整
                xVariation: 60
                yVariation: 20
            }
            //元素行進加速度設置,使用點方式模式
            acceleration: PointDirection {
                x: 12
                //隨著變數調整
                xVariation: 6
                yVariation: 5
            }
        }

        ImageParticle {
            system: myParticleSystem
            //Qt自帶粒子圖,可以換成自定義圖片
            source: "qrc:///particleresources/fuzzydot.png"
            //粒子圖使用白色
            color: "white"
            //顏色隨機繫數
            colorVariation: 0.1
        }

        ParallelAnimation {
            id: myAnimation

            //數值動畫
            NumberAnimation {
                //設定動畫的目標
                target: myEmitter
                //設定改變的屬性是x坐標
                properties: "x"
                //x移動到父視窗的邊沿
                to: root.width
                //在1秒內完成移動
                duration: 1000
            }

            SequentialAnimation {
                PropertyAnimation {
                    target: myGradientStart
                    properties: "color"
                    to: "#00FFFFFF"
                    duration: 200
                }

                ParallelAnimation {
                    PropertyAnimation {
                        target: myGradientEnd
                        properties: "position"
                        to: "1.0"
                        duration: 1000
                    }

                    PropertyAnimation {
                        target: myGradientStart
                        properties: "position"
                        to: "0.9"
                        duration: 1000
                    }
                }

                PropertyAnimation {
                    target: myGradientEnd
                    properties: "color"
                    to: "#00FFFFFF"
                    duration: 200
                }
            }
        }

        MouseArea {
            anchors.fill: parent

            //滑鼠點擊測試
            onClicked: {
                //讓myEmitter視窗複位,這樣滑鼠可重覆點擊
                if (myEmitter.x > 0)
                {
                    myAnimation.stop()
                    myEmitter.x = 0;

                    myGradientStart.position = 0.0
                    myGradientStart.color = "#FFFFFFFF"

                    myGradientEnd.position = 0.1
                    myGradientEnd.color = "#FFFFFFFF"
                }

                //激活粒子系統
                myParticleSystem.restart()
                //激活動畫
                myAnimation.restart()
            }
        }
    }
}

在以上代碼中簡單修改,就可以實現圖6的效果了。

4,總結

此常式主要使用的功能塊粒子系統,給粒子增加一些隨機設置參數,可以讓粒子系統顯示更自然。另外在粒子系統中還有很有趣的功能如精靈顯示、粒子影響器等等。另外一個主要的功能就是漸變功能,可以讓顏色A過渡到顏色B,及本常式中使用的從無色A過渡到有色B。

 https://www.simbahiker.com/news/0220200428001.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 框架結構 實體層: Typecho.Enties 倉儲層: Typecho.IRepository IconcardContext.cs IRepositoryFactory.cs IRepositorys.cs Typecho.Repository RepositoryFactory.cs Rep ...
  • 0. 前言 不知道有沒有動手能力強的小伙伴照著上一篇的內容寫過程式呢?如果有的話,應該會在使用的時候發現以下幾個問題: 1. 每次啟動都需要經過漫長的時間去遍歷磁碟里的文件目錄 2. 因為數據是用的字典保存的,所以會消耗大量的記憶體空間 3. 不能多次查詢 現在我們就針對這些問題,讓我們的小工具實用起 ...
  • 環境準備 需要一個linux操作系統:我這裡用的是ubuntu 18.04,安裝步驟就不說了,網上很多教程,當然也可以私信我。 既然需要用到docker,那麼就安裝個docker,apt install docker ce。 查看版本,這樣docker就算是成功安裝好了。 載入基礎鏡像 為了到時候b ...
  • out的使用 ————————————————————————————————————————————————— class Program { static void Main(string[] args) { string tmp; //先聲明,但不初始化 User _user=new User ...
  • 由於微軟的一些迷之bug,像click事件一樣直接在事件中生成的方法無法觸發,包括MouseLeftButtonDown等,必須採取手動方法: 1.新建路由事件: private void bt_MouseDown(object sender, RoutedEventArgs e) { //bili ...
  • 通過閱讀 WPF 官方開源倉庫的代碼和文檔,可以瞭解到在進行獨立發佈的時候會在倉庫裡面帶上 vcruntime140 的原因 ...
  • 使用阿裡雲ECS或者其他常見的VPS服務部署應用的時候,需要手動配置環境,並且監測ECS的行為,做補丁之類的,搞得有點複雜。好在很多雲廠商(阿裡雲、Azure等)提供了Serverless服務,藉助於Serverless,開發人員可以更加專註於代碼的開發,減少運維的成本。 Azure的部署直接集成在 ...
  • tune2fs命令允許系統管理員在Linux ext2、ext3或ext4文件系統上調整、設置、查看文件系統參數。tune2fs -l 只會顯示 superblock 上的內容。有時候使用tune2fs命令遇到類似“Couldn't find valid filesystem superblock”... ...
一周排行
    -Advertisement-
    Play Games
  • 前言 插件化的需求主要源於對軟體架構靈活性的追求,特別是在開發大型、複雜或需要不斷更新的軟體系統時,插件化可以提高軟體系統的可擴展性、可定製性、隔離性、安全性、可維護性、模塊化、易於升級和更新以及支持第三方開發等方面的能力,從而滿足不斷變化的業務需求和技術挑戰。 一、插件化探索 在WPF中我們想要開 ...
  • 歡迎ReaLTaiizor是一個用戶友好的、以設計為中心的.NET WinForms項目控制項庫,包含廣泛的組件。您可以使用不同的主題選項對項目進行個性化設置,並自定義用戶控制項,以使您的應用程式更加專業。 項目地址:https://github.com/Taiizor/ReaLTaiizor 步驟1: ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • Channel 是乾什麼的 The System.Threading.Channels namespace provides a set of synchronization data structures for passing data between producers and consume ...
  • efcore如何優雅的實現按年分庫按月分表 介紹 本文ShardinfCore版本 本期主角: ShardingCore 一款ef-core下高性能、輕量級針對分表分庫讀寫分離的解決方案,具有零依賴、零學習成本、零業務代碼入侵適配 距離上次發文.net相關的已經有很久了,期間一直在從事java相關的 ...
  • 前言 Spacesniffer 是一個免費的文件掃描工具,通過使用樹狀圖可視化佈局,可以立即瞭解大文件夾的位置,幫助用戶處理找到這些文件夾 當前系統C盤空間 清理後系統C盤空間 下載 Spacesniffer 下載地址:https://spacesniffer.en.softonic.com/dow ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • 一、ReZero簡介 ReZero是一款.NET中間件 : 全網唯一開源界面操作就能生成API , 可以集成到任何.NET6+ API項目,無破壞性,也可讓非.NET用戶使用exe文件 免費開源:MIT最寬鬆協議 , 一直從事開源事業十年,一直堅持開源 1.1 純ReZero開發 適合.Net Co ...
  • 一:背景 1. 講故事 停了一個月沒有更新文章了,主要是忙於寫 C#內功修煉系列的PPT,現在基本上接近尾聲,可以回頭繼續更新這段時間分析dump的一些事故報告,有朋友微信上找到我,說他們的系統出現了大量的http超時,程式不響應處理了,讓我幫忙看下怎麼回事,dump也抓到了。 二:WinDbg分析 ...
  • 開始做項目管理了(本人3年java,來到這邊之後真沒想到...),天天開會溝通整理需求,他們講話的時候忙裡偷閑整理一下常用的方法,其實語言還是有共通性的,基本上看到方法名就大概能猜出來用法。出去打水的時候看到外面太陽好好,真想在外面坐著曬太陽,回來的時候好兄弟三年前送給我的鍵盤D鍵不靈了,在打"等待 ...