• 2738阅读
  • 1回复

Qml特效1-进场动画-飞入 [复制链接]

上一主题 下一主题
离线dd759378563
 

只看楼主 倒序阅读 楼主  发表于: 2019-06-09


Qml特效1-进场动画-飞入


目录
(放个目录方便预览。这个目录是从博客复制过来的,点击会跳转到博客)
ShaderEffect飞入效果源码

简介

这是《Qml特效-进场动画》系列文章的第一篇,涛哥将会教大家一些Qml进场动画相关的知识。


关于文章

《Qml组件化编程》系列文章,已经发布了10篇,暂时没有更多内容了,后续可能会更新,看情况。
涛哥开始了新的系列文章《Qml特效》,计划是三部曲《Qml特效-进场动画》
《Qml特效-页面切换动画》《Qml特效-3D特效》,欢迎大家关注。
进场动画效果 参考了WPS版ppt的动画,基本效果已经全部实现,可以到github TaoQuick项目中预览:
https://github.com/jaredtao/TaoQuick/blob/master/Preview-animation.md




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


进入效果预览

第一篇文章,就放一个简单的进入动画







实现原理

进场动画,使用了QtQuick的动画系统,以及ShaderEffect特效。
Qml中有一个模块QtGraphicalEffects,提供了部分特效,就是使用ShaderEffect实现的。
使用ShaderEffect实现特效,需要有一些OpenGL/DirectX知识,了解GPU渲染管线,同时也需要一些数学知识。


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这个组件,就能实现像素级别的操作。
大名鼎鼎的ShaderToy网站,就是使用Shader实现各种像素级别的酷炫特效。
ShaderToy
作者iq大神
ShaderToy上面的特效都是可以移植到Qml中的。
使用Shader开发,需要一定的图形学知识。其中使用GLSL需要熟悉OpenGL, 使用HLSL需要熟悉DirectX。


进入效果源码

封装了一个平移进入的动画组件,能够支持从四个方向进场。
  1. //ASlowEnter.qml
  2. import QtQuick 2.12
  3. import QtQuick.Controls 2.12
  4. import "../.."
  5. Item {
  6.     id: r
  7.     property int targetX: 0
  8.     property int targetY: 0
  9.     property alias animation: animation
  10.     enum Direct {
  11.         FromLeft = 0,
  12.         FromRight = 1,
  13.         FromTop = 2,
  14.         FromBottom = 3
  15.     }
  16.     property int dir: ASlowEnter.Direct.FromBottom
  17.     property int duration: 2000
  18.     //额外的距离,组件在父Item之外时,额外移动一点,避免边缘暴露在父Item的边缘
  19.     property int extDistance: 10
  20.     property var __propList: ["x", "x", "y", "y"]
  21.     property var __fromList: [
  22.         -r.parent.width - r.width - extDistance,
  23.         r.parent.width + r.width + extDistance,
  24.         -r.parent.height - r.height - extDistance,
  25.         r.parent.height + r.height + extDistance]
  26.     property var __toList: [targetX, targetX, targetY, targetY]
  27.     NumberAnimation {
  28.         id: animation
  29.         target: r
  30.         property: __propList[dir]
  31.         from: __fromList[dir]
  32.         to: __toList[dir]
  33.         duration: r.duration
  34.         loops: 1
  35.         alwaysRunToEnd: true
  36.     }
  37. }





进场组件的使用
  1. //Enter.qml
  2. import QtQuick 2.12
  3. import QtQuick.Controls 2.12
  4. import "../Animation/Enter"
  5. Item {
  6.     anchors.fill: parent
  7.     ASlowEnter {
  8.         id: a1
  9.         width: 160
  10.         height: 108
  11.         x: (parent.width - width) / 2
  12.         targetY: parent.height / 2
  13.         dir: ASlowEnter.Direct.FromBottom
  14.         Image {
  15.             anchors.fill: parent
  16.             source: "qrc:/EffectImage/Img/baby.jpg"
  17.         }
  18.     }
  19.     ASlowEnter {
  20.         id: a2
  21.         width: 160
  22.         height: 108
  23.         x: (parent.width - width) / 2
  24.         targetY: parent.height / 2 - height
  25.         dir: ASlowEnter.Direct.FromTop
  26.         Image {
  27.             anchors.fill: parent
  28.             source: "qrc:/EffectImage/Img/baby.jpg"
  29.         }
  30.     }
  31.     ASlowEnter {
  32.         id: a3
  33.         width: 160
  34.         height: 108
  35.         targetX: parent.width / 2 - width * 1.5
  36.         y: (parent.height - height) / 2
  37.         dir: ASlowEnter.Direct.FromLeft
  38.         Image {
  39.             anchors.fill: parent
  40.             source: "qrc:/EffectImage/Img/baby.jpg"
  41.         }
  42.     }
  43.     ASlowEnter {
  44.         id: a4
  45.         width: 160
  46.         height: 108
  47.         targetX: parent.width / 2 + width / 2
  48.         y: (parent.height - height) / 2
  49.         dir: ASlowEnter.Direct.FromRight
  50.         Image {
  51.             anchors.fill: parent
  52.             source: "qrc:/EffectImage/Img/baby.jpg"
  53.         }
  54.     }
  55.     ParallelAnimation {
  56.         id: ani
  57.         ScriptAction{ script: {a1.animation.restart()} }
  58.         ScriptAction{ script: {a2.animation.restart()} }
  59.         ScriptAction{ script: {a3.animation.restart()} }
  60.         ScriptAction{ script: {a4.animation.restart()} }
  61.     }
  62.     Component.onCompleted: {
  63.         ani.restart()
  64.     }
  65.     Button {
  66.         anchors.right: parent.right
  67.         anchors.bottom: parent.bottom
  68.         text: "replay"
  69.         onClicked: {
  70.             ani.restart()
  71.         }
  72.     }
  73. }








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

只看该作者 1楼 发表于: 2020-04-14
快速回复
限100 字节
 
上一个 下一个