26.Qt Quick QML-RotationAnimation、PathAnimation、SmoothedAnimation、Behavior、PauseAnimation、SequentialAnimation和ParallelAnimation
- 2021 年 6 月 5 日
- 笔记
- 4.5 Qt Quick
1.RotationAnimation
RotationAnimation也是继承于PropertyAnimation组件,但是它有点特殊,它只需要指定taget目标对象,并且不需要指定property,因为rotation就是要绑定的属性.并且它还多了个direction属性:
- direction : enumeration,设置旋转的方向,取值有:
- RotationAnimation.Numerical (默认值) – 数值旋转,通过to-from得出要旋转的度数,然后进行旋转,比如from为10,to为100,那么旋转就是90°
- RotationAnimation.Clockwise – 在两个度数之间进行顺时针旋转,比如from为10,to为100,那么顺旋转就是90°
- RotationAnimation.Counterclockwise – 在两个度数之间进行逆时针旋转,比如from为10,to为100,那么逆旋转就是90°
- RotationAnimation.Shortest – 沿最短路径的方向旋转。比如from为10,to为350,那么将逆时针旋转20°
示例如下所示:
property var rotationModel: [ ["#00FF00", RotationAnimation.Numerical], ["#FF0000", RotationAnimation.Clockwise], ["#0000FF", RotationAnimation.Counterclockwise], ["#00FFFF", RotationAnimation.Shortest], ] property var animations: new Array(0) MouseArea { id: area anchors.fill: parent onPressed: { for (var i in animations) { console.log(animations[i].direction) animations[i].start(); } } } Row { spacing: 10 Repeater { model: rotationModel.length Rectangle { id: rect width: 100 height: 100 radius: width / 2 color: rotationModel[index][0] Text { anchors.centerIn: parent text: "model"+ index.toString() color: "white" font.pixelSize: 18 font.bold: true } RotationAnimation { running: true duration: 500 target: rect direction: rotationModel[index][1] from : 10 to : 350 Component.onCompleted: animations[index] = this } } } }
效果如下所示:
2.PathAnimation
PathAnimation继承于Animation组件,用来实现一个路径动画.
它的属性如下所示:
- anchorPoint : point,设置目标瞄点,默认为目标的左上角(其0,0点)将定位到(或跟随)路径。比如10×10的Rectangle,那么anchorPoint为Qt.point(5, 5)时则表示始终让物体中心处于路径上
- duration : int,持续时间
- easing.type : enumeration,设置动画的缓和曲线.默认值为Easing.Linear(线性过程),比如我们设置为Easing.InQuad时,动画效果就是从慢到快的过程.
- easing.amplitude : real,设置缓和曲线的振幅,默认值为1.0,值越大振幅越大,仅当easing.type为Easing.InBounce, Easing.OutBounce, Easing.InOutBounce, Easing.OutInBounce, Easing.InElastic, Easing.OutElastic, Easing.InOutElastic or Easing.OutInElastic才生效
- orientation : enumeration,设置对象在路径上的方向,取值有以下几种:
- PathAnimation.Fixed (default) – 在动画中只是移动物体,并不旋转物体
- PathAnimation.RightFirst – 始终让目标的右侧在前面沿着路径移动
- PathAnimation.LeftFirst – 始终让目标的左侧在前面沿着路径移动
- PathAnimation.BottomFirst – 始终让目标的底部在前面沿着路径移动
- PathAnimation.TopFirst – 始终让目标的顶部在前面沿着路径移动
- endRotation : real,设置目标移动路径结束后的旋转角度,如果orientationEntryDuration未设置,物体则会直接跳转到该值,否则就以动画的形式结束
- orientationEntryDuration : real,设置启动时的旋转过渡时间(毫秒单位),比如启动动画时,如果当前目标方向和orientation值方向不一致,则需要一个过渡时间才行
- orientationExitDuration : real,设置结束时的旋转过渡时间(毫秒单位),如果endRotation已设置,那么就会有个过渡时间,让物体最终旋转到endRotation角度.
- target : Item ,设置动画的目标对象
- path : Path,设置动画的路径。
接下来我们便来讲解Path路径
3.Path
一个Path可以由下面多个Path段组成:
- PathLine : 由一个坐标指定的直线路径
- PathPolyline : 由一个path坐标列表指定的多段路径
- PathQuad : 由一个控制点生成的二次贝塞尔曲线路径
- PathCubic : 由两个控制点生成的三次贝塞尔曲线路径
- PathArc : 由结束坐标,以及一个radiusX和radiusY半径实现的一个圆弧(顺时针绘画)
- PathAngleArc : 由中心点、半径和起始角度startAngle、旋转角度sweepAngle指定的圆弧。
- PathCurve :由一个坐标点生成的curve曲线路径(通常需要配合多个PathCurve才行)
- PathSvg : 由SVG路径字符串实现的路径。你可以用它创建线条, 曲线, 弧形等等
显示一个Path路径
我们可以通过设置context2D的path属性,来显示出我们绘画的Path路径,不然都不知道绘制的路径到底对不对,真是“半夜吃黄瓜-摸不着头尾”
我们以PathArc为例,示例如下所示:
Canvas { id: canvas anchors.fill: parent antialiasing: true onPaint: { var context = canvas.getContext("2d") context.clearRect(0, 0, width, height) context.strokeStyle = "black" context.path = path context.stroke() } } Path { id: path startX: 100; startY: 100 PathArc { x: 100; y: 140 radiusX: 100; radiusY: 50 useLargeArc: true xAxisRotation: 30 } }
效果如下所示:
这里我们设置弧线的起始位置为(100,100),终点位置为(100,140).
它的useLargeArc为true,表示使用角度大的那个圆弧,如果设置为false,则将会使用小的那个圆弧
它的xAxisRotation表示x水平方向是否倾斜,我们这里按顺时针倾斜了30°,该值仅在x和y半径不同时有用,这意味着圆弧是椭圆形的
接下来我们便来学习PathSvg路径.
4.PathSvg
PathSvg支持的命令如下所示:
- M = moveto,移动画笔到指定点处(只是移动位置,不画线),写法:M x y
- L = lineto,从当前点绘制一条直线到目的点,写法:L x y
- H = horizontal lineto,绘制一条平行线,写法:H x
- V = vertical lineto,绘制一条垂直线,写法:V y
- C = curveto,绘制一条三次贝塞尔曲线,写法:C x1 y1, x2 y2, x y (x和y为终点,其它两个为控制点)
- S = smooth curveto,用来写在C命令后面时来延长贝塞尔曲线,当然也可以跟在S命令后面,写法:S x1 y1, x y(x1和y1是控制点,x和y是终点)
- Q = quadratic Bézier curve,绘制一条二次贝塞尔曲线,写法:Q x1 y1, x y
- T = smooth quadratic Bézier curveto,用来写在Q命令后面时来延长贝塞尔曲线,当然也可以跟在T命令后面,写法:T x y
- A = elliptical Arc,绘制一条圆弧,写法:A rx ry x-axis-rotation large-arc-flag sweep-flag x y
- rx、ry:表示圆弧的半径
- x-axis-rotation: 表示x水平方向是否倾斜,比如设置为-45,则圆弧会逆时针倾斜45°,注意:该值仅在x和y半径不同时有用,这意味着圆弧是椭圆形的
- large-arc-flag:设置为0表示绘制小圆弧,为1表示大圆弧
- sweep-flag: 表示弧线的方向,0表示从起点到终点沿逆时针画弧,1表示从起点到终点沿顺时针画弧
- x、y:表示绘制的终点位置
- Z = closepath,关闭路径,将会从当前点绘制一条直线到开始点.
5.PathAnimation使用PathSvg示例
Canvas { id: canvas anchors.fill: parent antialiasing: true onPaint: { var context = getContext("2d") context.clearRect(0, 0, width, height) context.strokeStyle = "red" context.path = pathAnim.path context.stroke() } } PathAnimation { id: pathAnim running: true loops: Animation.Infinite duration: 5000 easing.type: Easing.InQuad target: car orientation: PathAnimation.RightFirst anchorPoint: Qt.point(car.width/2, car.height) path: Path { startX: 100; startY: 100 PathSvg { path: "M100 100 C600 50, 50 300, 550 250" } } } Item { id: car x: 25; y: 25 width: 80; height: 38 Canvas { id: canvas2 anchors.fill: parent antialiasing: true onPaint: { var context = getContext("2d") context.clearRect(0, 0, width, height) context.fillStyle = "blue" context.fillRect(0,0,width,height-10) context.fillStyle = "yellow" context.ellipse(10,height-20,20,20) context.ellipse(width-30,height-20,20,20) context.fill() console.log(width,height) } } Text { anchors.centerIn: parent text: "小车" color: "white" } }
效果如下所示:
6.SmoothedAnimation
SmoothedAnimation继承于NumberAnimation组件,它比NumberAnimation更加人性化,不仅可以设置duration时间,还可以设置滑动速率。
并且SmoothedAnimation的easing.type默认值为Easing.InOutQuad(慢->快->慢).
SmoothedAnimation如果同时指定了velocity速度和duration持续时间,则会选择导致动画速度最快的那个所需时间.
例如:
- 如果velocity速度设置为200,如果duration设置为5000.
- 假如此时需要将一个物体从0位移到800,那么此时将会选择velocity速度的时间,因为只需要4秒时间.
- 假如此时需要将一个物体从0位移到2000,那么此时将会选择duration时间,因为只需要5秒时间.
它的属性如下所示:
- duration : int,持续时间,默认值为-1.表示禁用持续时间值。
- reversingMode : enumeration,设置如果动画方向被突然被反转后的行为(比如当前动画正在往左边移动时,突然用户让动画往右边移动),取值如下所示:
- SmoothedAnimation.Eased(默认)-动画将按照速度平滑减速到0后,开始反转方向加速
- SmoothedAnimation.Immediate-动画将立即以0的速度开始反向加速
- SmoothedAnimation.Sync-立即将属性设置为目标值
- velocity : real,设置速度,默认值为200(200像素点每秒),如果将此设置为-1(默认值)将禁用速度值。
示例如下所示:
MouseArea { anchors.fill: parent hoverEnabled: true onPositionChanged: { animation1.to = mouseX - rect.width/2 animation2.to = mouseY - rect.height/2 animation1.restart() animation2.restart() } } Rectangle { id: rect color: "red" width: 60; height: 60 radius: width/2 SmoothedAnimation on x{ id: animation1 velocity: 100 reversingMode: SmoothedAnimation.Immediate } SmoothedAnimation on y{ id: animation2 velocity: 100 reversingMode: SmoothedAnimation.Immediate } }
只要当我们鼠标位置发生改变就会启动SmoothedAnimation动画进行平滑移动,但是我们这样写,代码显得有点繁琐,可以使用Behavior组件来代替设置from和to的行为来节省代码量
接下来我们来给大家讲讲Behavior.
7.Behavior
Behavior用来让动画绑定到对象一个属性上,Behavior中文翻译就是行为的意思,所以当绑定属性发生改变时,就会自动触发Behavior行为,Behavior就会自动设置动画的to属性,并启动动画.
Behavior只有两个属性animation和enabled, animation保存着要触发行为的哪个动画,enabled表示是否使能行为,默认为true.
Behavior示例如下所示:
MouseArea { anchors.fill: parent hoverEnabled: true onPositionChanged: { rect.x = mouseX - rect.width/2 rect.y = mouseY - rect.height/2 } } Rectangle { id: rect color: "red" width: 60; height: 60 radius: width/2 Behavior on x { SmoothedAnimation { velocity: 100 reversingMode: SmoothedAnimation.Immediate } } Behavior on y { SmoothedAnimation { velocity: 100 reversingMode: SmoothedAnimation.Immediate } } }
这里我们使用Behavior分别为属性绑定了SmoothedAnimation动画,然后我们只需要改变x,y属性,就会自动触发行为,设置我们改变的值到动画的to属性中,并启动动画
8.PauseAnimation
PauseAnimation顾名思义就是暂停动画的意思,只有一个duration属性,用来设置该期间内什么都不做.
并且只能在SequentialAnimation动画中使用,接下来我们便来学习SequentialAnimation和ParallelAnimation,并在代码中使用它
9.SequentialAnimation和ParallelAnimation
SequentialAnimation用来将多个动画串行地执行下去.而ParallelAnimation是用来将多个动画并行地执行下去.
并且SequentialAnimation和ParallelAnimation还可以互相嵌套.
需要注意的是:
- SequentialAnimation或ParallelAnimation中定义的动画不能单独启动和停止;必须作为一个组来启动和停止。
- 并且SequentialAnimation和ParallelAnimation的running默认为false.如果要想加载组件后立即启动的话,我们需要手动设置(不需要全部设置,只需要设置最顶层动画的running值即可)
示例如下所示:
Window{ id: window width: 480 height: 320 visible: true SequentialAnimation { SequentialAnimation { ParallelAnimation { NumberAnimation { target: ball1 property: "y" from: 20 to: height - ball1.height - 20 easing.type: Easing.OutBounce; duration: 1200 } NumberAnimation { target: ball2 property: "y" from: 20 to: height - ball2.height - 20 easing.type: Easing.OutBounce; duration: 800 } } } PauseAnimation { duration: 500 } running: true loops: Animation.Infinite } Rectangle { id: ball1 width: 40; height: 40; radius: 20 color: "blue" x: 30 } Rectangle { id: ball2 width: 60; height: 60; radius: 30 color: "red" x: 200 } }
效果如下所示:
如上图所示,可以看到每当小球落到地后,就会启动PauseAnimation暂停动画,等待500ms