• 4258阅读
  • 7回复

Qml特效15-暗流涌动 [复制链接]

上一主题 下一主题
离线dd759378563
 

图酷模式  只看楼主 倒序阅读 楼主  发表于: 2019-06-11
Qml特效15-暗流涌动

作者 涛哥



目录简介


简介


这是《Qml特效》系列文章的第15篇,涛哥将会教大家一些Qml特效和动画相关的知识。
前12篇是进场动画效果 参考了WPS版ppt的动画,12种基本效果已经全部实现,可以到github TaoQuick项目中预览:
进场动画预览


因为效果都比较简单,就没有写太多说明。
没有13
没有13
没有13
从14篇开始,做一些特殊的效果和动画,同时会讲解相关的知识。

关于文章


文章主要发布在涛哥的博客涛哥的知乎专栏-Qt进阶之路

暗流涌动 效果预览


流动的箭头,以及倒影

其中用到的知识点有: Qml路径动画。
当然还有一些预备知识:做特效和动画,要用到QtQuick的动画系统,以及ShaderEffect特效。

QtQuick动画系统



动画组件


Qt动画系统,在帮助文档有详细的介绍,搜索关键词”Animation”,涛哥在这里说一些重点。涛哥用思维导图列出了Qml中所有的动画组件:




  • 右边带虚线框的部分比较常用,是做动画必须要掌握的,尤其是属性动画PropertyAnimation和数值动画NumberAinmation。
    常见的各种坐标动画、宽高动画、透明度动画、颜色动画等等,都可以用这些组件来实现。
  • 底下的States、Behavior 和 Traisitions,也是比较常用的和动画相关的组件。可在帮助文档搜索
    关键词”Qt Quick States”、”Behavior”、”Animation and Transitions”。后续的文章,涛哥会专门讲解。
  • 左边的Animator系列,属于Scene Graph渲染层面的优化,其属性Change信号只在最终值时发出,不发出中间值,使用的时候需要注意。
  • 顶上的AnimationController,属于高端玩家,用来控制整个动画的进度。


动画的使用



用例一 直接声明动画


直接声明动画,指定target和property,之后可以在槽函数/js脚本中通过id控制动画的运行。也可以通过设定loops 和 running属性来控制动画
  1. Rectangle {
  2.       id: flashingblob
  3.       width: 75; height: 75
  4.       color: "blue"
  5.       opacity: 1.0
  6.       MouseArea {
  7.           anchors.fill: parent
  8.           onClicked: {
  9.               animateColor.start()
  10.               animateOpacity.start()
  11.           }
  12.       }
  13.       PropertyAnimation {id: animateColor; target: flashingblob; properties: "color"; to: "green"; duration: 100}
  14.       NumberAnimation {
  15.           id: animateOpacity
  16.           target: flashingblob
  17.           properties: "opacity"
  18.           from: 0.99
  19.           to: 1.0
  20.           loops: Animation.Infinite
  21.           easing {type: Easing.OutBack; overshoot: 500}
  22.      }
  23.   }




用例二 on语法


on语法可以使用动画组件,也可以用Behavior,直接on某个特定的属性即可。效果一样。on动画中,如果直接指定了running属性,默认就会执行这个动画。
也可以不指定running属性,其它地方修改这个属性时,会自动按照动画来执行。


示例代码 on动画
  1. Rectangle {
  2.       width: 100; height: 100; color: "green"
  3.       RotationAnimation on rotation {
  4.           loops: Animation.Infinite
  5.           from: 0
  6.           to: 360
  7.           running: true
  8.       }
  9.   }
示例代码 Behavior 动画
  1. import QtQuick 2.0
  2.   Rectangle {
  3.       id: rect
  4.       width: 100; height: 100
  5.       color: "red"
  6.       Behavior on width {
  7.           NumberAnimation { duration: 1000 }
  8.       }
  9.       MouseArea {
  10.           anchors.fill: parent
  11.           onClicked: rect.width = 50
  12.       }
  13.   }





用例三 Transitions或状态机


过渡动画和状态机动画,本质还是直接使用动画组件。只不过是把动画声明并存储起来,以在状态切换时使用。这里先不细说了,后面会有系列文章<Qml特效-页面切换动画>,会专门讲解。

ShaderEffect


动画只能控制组件的属性整体的变化,做特效需要精确到像素。Qml中提供了ShaderEffect这个组件,就能实现像素级别的操作。
Qml中有一个模块QtGraphicalEffects,提供了部分特效,就是使用ShaderEffect实现的。使用ShaderEffect实现特效,需要有一些OpenGL/DirectX知识,了解GPU渲染管线,同时也需要一些数学知识。
大名鼎鼎的ShaderToy网站,就是使用Shader实现各种像素级别的酷炫特效。ShaderToy
作者iq大神ShaderToy上面的特效都是可以移植到Qml中的。
使用Shader开发,需要一定的图形学知识。其中使用GLSL需要熟悉OpenGL, 使用HLSL需要熟悉DirectX。

暗流涌动 效果源码



组件的封装


封装了一个组件
  1. //TArrow.qml
  2. import QtQuick 2.12
  3. import QtQuick.Controls 2.12
  4. Image {
  5.     id: root
  6.     x: 10
  7.     y: 10
  8.     source: "qrc:/EffectImage/Img/arrow.png"
  9.     visible: false
  10.     function run() {
  11.         visible = true;
  12.         pathAnimation.start();
  13.     }
  14.     PathAnimation {
  15.         id: pathAnimation
  16.         target: root
  17.         loops: -1
  18.         duration: 2400
  19.         orientation: PathAnimation.TopFirst
  20.         path: Path{
  21.             startX: 10
  22.             startY: 10
  23.             PathCurve { x: 60; y: 15}
  24.             PathCurve { x: 110; y: 205}
  25.             PathCurve { x: 210; y: 200}
  26.             PathCurve { x: 260; y: 35}
  27.             PathCurve { x: 310; y: 25}
  28.         }
  29.     }
  30. }




原理


很简单的路径动画,使用的箭头图片是这张:




组件的使用
  1. import QtQuick 2.12
  2. import QtQuick.Controls 2.12
  3. import "../Effects/"
  4. Rectangle {
  5.     anchors.fill: parent
  6.     color: "black"
  7.     Item {
  8.         id: arrowItem
  9.         x: 10
  10.         y: 10
  11.         width: 300
  12.         height: 300
  13.         TArrow {
  14.             id: arrow1
  15.         }
  16.         TArrow {
  17.             id: arrow2
  18.         }
  19.         TArrow {
  20.             id: arrow3
  21.         }
  22.         TArrow {
  23.             id: arrow4
  24.         }
  25.         TArrow {
  26.             id: arrow5
  27.         }
  28.         TArrow {
  29.             id: arrow6
  30.         }
  31.         TArrow {
  32.             id: arrow7
  33.         }
  34.         TArrow {
  35.             id: arrow8
  36.         }
  37.         TArrow {
  38.             id: arrow9
  39.         }
  40.     }
  41.     Item {
  42.         id: mirrorItem
  43.         x: arrowItem.x
  44.         y: arrowItem.y + arrowItem.height
  45.         width: arrowItem.width
  46.         height: arrowItem.height
  47.         opacity: 0.3
  48.         layer.enabled: true
  49.         layer.effect: Component {
  50.             ShaderEffectSource {
  51.                 sourceItem: arrowItem
  52.                 textureMirroring: ShaderEffectSource.MirrorVertically
  53.             }
  54.         }
  55.         transform: Rotation {
  56.             origin.x: mirrorItem.width / 2
  57.             origin.y: mirrorItem.height / 2
  58.             axis {x: 1; y: 0; z: 0}
  59.             angle: 180
  60.         }
  61.     }
  62.     Component.onCompleted: {
  63.         seAnimation.start()
  64.     }
  65.     SequentialAnimation {
  66.         id: seAnimation
  67.         ScriptAction {script: arrow1.run()}
  68.         PauseAnimation {duration: 200 }
  69.         ScriptAction {script: arrow2.run()}
  70.         PauseAnimation {duration: 200 }
  71.         ScriptAction {script: arrow3.run()}
  72.         PauseAnimation {duration: 500 }
  73.         ScriptAction {script: arrow4.run()}
  74.         PauseAnimation {duration: 200 }
  75.         ScriptAction {script: arrow5.run()}
  76.         PauseAnimation {duration: 200 }
  77.         ScriptAction {script: arrow6.run()}
  78.         PauseAnimation {duration: 500 }
  79.         ScriptAction {script: arrow7.run()}
  80.         PauseAnimation {duration: 200 }
  81.         ScriptAction {script: arrow8.run()}
  82.         PauseAnimation {duration: 200 }
  83.         ScriptAction {script: arrow9.run()}
  84.         PauseAnimation {duration: 200 }
  85.     }
  86. }



动画比较简单粗暴。

倒影这里,和《Qml特效14-跟上节奏》使用的不一样,使用的是Item的layer属性

layer.enabled: true

layer.effect: Component {
ShaderEffectSource {
...
}
}






涛哥是个Qml高手,著有《Qml组件化编程》《Qml特效》系列教程,见知乎专栏-Qt进阶之路:https://zhuanlan.zhihu.com/TaoQt
或微信公众号:Qt进阶之路
离线liulin188

只看该作者 1楼 发表于: 2019-06-12
https://wiki.qt.io/Qt_5.12_Release
https://wiki.qt.io/New_Features_in_Qt_5.12
https://wiki.qt.io/Qt_5.12.0_Known_Issues
https://www.qt.io/blog/qt-5.13.2-released
https://www.qt.io/blog/qt-creator-4.10.2-released
https://wiki.qt.io/Qt_5.12_Tools_and_Versions
离线john_duan

只看该作者 2楼 发表于: 2019-06-13
离线liudianwu

只看该作者 3楼 发表于: 2019-06-13
欢迎关注微信公众号:Qt实战 (各种开源作品、经验整理、项目实战技巧,专注Qt/C++软件开发,视频监控、物联网、工业控制、嵌入式软件、国产化系统应用软件开发)QQ:517216493  WX:feiyangqingyun  QQ群:751439350
离线qyvlik

只看该作者 4楼 发表于: 2019-06-14
大佬,能单独来份 ShaderEffect 的入门教学吗?例如在 QML 中使用 GLSL 需要哪些具体的知识,怎么做出一个好看的特效。
ubiboot
离线dd759378563

只看该作者 5楼 发表于: 2019-06-14
回 qyvlik 的帖子
qyvlik:
大佬,能单独来份 ShaderEffect 的入门教学吗?例如在 QML 中使用 GLSL 需要哪些具体的知识,怎么做出一个好看的特效。

吓我一跳, qyvlik 你才是大佬,我从你的CSDN学了不少东西呢。
我学习过OpenGL,懂一点图形学,
那我这周末试着总结一下,写好了通知你。
涛哥是个Qml高手,著有《Qml组件化编程》《Qml特效》系列教程,见知乎专栏-Qt进阶之路:https://zhuanlan.zhihu.com/TaoQt
或微信公众号:Qt进阶之路
离线richards

只看该作者 6楼 发表于: 2019-06-15
大佬 你的导图是什么软件画的
离线bobpan

只看该作者 7楼 发表于: 2019-07-13
快速回复
限100 字节
 
上一个 下一个