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.Windows 2.2
- import QtQuick.Particles 2.0
- Windows {
- 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.Windows 2.2
- import QtQuick.Particles 2.0
- import QtGraphicalEffects 1.0
- Windows {
- 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
来源: https://www.cnblogs.com/hiker-blogs/p/12860533.html