目录
(放个目录方便预览。知乎不支持目录,这个目录是从博客复制过来的,点击会跳转到博客)
这是《Qml特效》系列文章的第15篇,涛哥将会教大家一些Qml特效和动画相关的知识。
前12篇是进场动画效果 参考了WPS版ppt的动画,12种基本效果已经全部实现,可以到github TaoQuick项目中预览:
进场动画预览
因为效果都比较简单,就没有写太多说明。
没有13
从14篇开始,做一些特殊的效果和动画,同时会讲解相关的知识。
文章主要发布在涛哥的博客 和 涛哥的知乎专栏-Qt进阶之路
流动的箭头,以及倒影
其中用到的知识点有: Qml路径动画。
当然还有一些预备知识:
做特效和动画,要用到QtQuick的动画系统,以及ShaderEffect特效。
Qt动画系统,在帮助文档有详细的介绍,搜索关键词」Animation」,涛哥在这里说一些重点。
涛哥用思维导图列出了Qml中所有的动画组件:
直接声明动画,指定target和property,之后可以在槽函数/js脚本中通过id控制动画的运行。
也可以通过设定loops 和 running属性来控制动画
Rectangle { id: flashingblob width: 75; height: 75 color: "blue" opacity: 1.0
MouseArea { anchors.fill: parent onClicked: { animateColor.start() animateOpacity.start() } }
PropertyAnimation {id: animateColor; target: flashingblob; properties: "color"; to: "green"; duration: 100}
NumberAnimation { id: animateOpacity target: flashingblob properties: "opacity" from: 0.99 to: 1.0 loops: Animation.Infinite easing {type: Easing.OutBack; overshoot: 500} } }
on语法可以使用动画组件,也可以用Behavior,直接on某个特定的属性即可。效果一样。
on动画中,如果直接指定了running属性,默认就会执行这个动画。
也可以不指定running属性,其它地方修改这个属性时,会自动按照动画来执行。
示例代码 on动画
Rectangle { width: 100; height: 100; color: "green" RotationAnimation on rotation { loops: Animation.Infinite from: 0 to: 360 running: true } }
示例代码 Behavior 动画
import QtQuick 2.0
Rectangle { id: rect width: 100; height: 100 color: "red"
Behavior on width { NumberAnimation { duration: 1000 } }
MouseArea { anchors.fill: parent onClicked: rect.width = 50 } }
过渡动画和状态机动画,本质还是直接使用动画组件。
只不过是把动画声明并存储起来,以在状态切换时使用。
这里先不细说了,后面会有系列文章,会专门讲解。
动画只能控制组件的属性整体的变化,做特效需要精确到像素。
Qml中提供了ShaderEffect这个组件,就能实现像素级别的操作。
Qml中有一个模块QtGraphicalEffects,提供了部分特效,就是使用ShaderEffect实现的。
使用ShaderEffect实现特效,需要有一些OpenGL/DirectX知识,了解GPU渲染管线,同时也需要一些数学知识。
大名鼎鼎的ShaderToy网站,就是使用Shader实现各种像素级别的酷炫特效。
ShaderToy
作者iq大神
ShaderToy上面的特效都是可以移植到Qml中的。
封装了一个组件TArrow
//TArrow.qml import QtQuick 2.12 import QtQuick.Controls 2.12 Image { id: root x: 10 y: 10 source: "qrc:/EffectImage/Img/arrow.png" visible: false function run() { visible = true; pathAnimation.start(); } PathAnimation { id: pathAnimation target: root loops: -1 duration: 2400 orientation: PathAnimation.TopFirst path: Path{ startX: 10 startY: 10 PathCurve { x: 60; y: 15} PathCurve { x: 110; y: 205} PathCurve { x: 210; y: 200} PathCurve { x: 260; y: 35} PathCurve { x: 310; y: 25} } } }
很简单的路径动画,使用的箭头图片是这张:
import QtQuick 2.12 import QtQuick.Controls 2.12 import "../Effects/" Rectangle { anchors.fill: parent color: "black" Item { id: arrowItem x: 10 y: 10 width: 300 height: 300 TArrow { id: arrow1 } TArrow { id: arrow2 } TArrow { id: arrow3 } TArrow { id: arrow4 } TArrow { id: arrow5 } TArrow { id: arrow6 } TArrow { id: arrow7 } TArrow { id: arrow8 } TArrow { id: arrow9 } } Item { id: mirrorItem x: arrowItem.x y: arrowItem.y + arrowItem.height width: arrowItem.width height: arrowItem.height opacity: 0.3 layer.enabled: true layer.effect: Component { ShaderEffectSource { sourceItem: arrowItem textureMirroring: ShaderEffectSource.MirrorVertically } } transform: Rotation { origin.x: mirrorItem.width / 2 origin.y: mirrorItem.height / 2 axis {x: 1; y: 0; z: 0} angle: 180 } } Component.onCompleted: { seAnimation.start() } SequentialAnimation { id: seAnimation ScriptAction {script: arrow1.run()} PauseAnimation {duration: 200 } ScriptAction {script: arrow2.run()} PauseAnimation {duration: 200 } ScriptAction {script: arrow3.run()}
PauseAnimation {duration: 500 }
ScriptAction {script: arrow4.run()} PauseAnimation {duration: 200 } ScriptAction {script: arrow5.run()} PauseAnimation {duration: 200 } ScriptAction {script: arrow6.run()}
ScriptAction {script: arrow7.run()} PauseAnimation {duration: 200 } ScriptAction {script: arrow8.run()} PauseAnimation {duration: 200 } ScriptAction {script: arrow9.run()} PauseAnimation {duration: 200 } } }
动画比较简单粗暴。