QML-动画
一、QML中的动画
1.1、动画类型
- 在QML中存在多种动画类型:
PropertyAnimation: 属性值改变播放动画–通用类型NumberAnimation:qreal-type值改变播放动画ColorAnimation:颜色值改变播放动画RotationAnimation:旋转值改变播放动画OpacityAnimation: 渐变透明
- 属性值改变播放的动画-PropertyAnimation
最通用的动画类型,可以动画任何属性。
import QtQuickImage{id: rootsource: "qrc:/image/bgd.jpg"anchors.fill: parentproperty int padding: 40property bool running: false// 资源加载状态检查onStatusChanged: {if(status === Image.Error){console.log("背景图片加载失败:", source)}else if(status === Image.Ready){console.log("背景图片加载成果...")}}Image{id:sssource: "qrc:/image/cd2.jpg"width: 50height: 50x:root.paddingy:(root.height - height) * 0.5// 资源加载状态检查onStatusChanged: {if(status === Image.Error){console.log("子图片加载失败:", source)}else if(status === Image.Ready){console.log("子图片...")}}// 平移动画PropertyAnimation on x{to:root.width - ss.widthduration: 3000running: root.running}// 旋转动画RotationAnimation on rotation {to:360duration: 3000running: root.running}// 颜色进行透明PropertyAnimation on opacity {to:0duration: 3000running: root.running}}MouseArea{anchors.fill: parentonClicked: {console.log("clicked...")root.running = true}}
}
注意:
此处是将动画放在控件里面,所有默认作用的对象是该控件;如果想放在控件之外,那么需要显示声明,目标对象,比如:
Image{id:sssource: "qrc:/image/cd2.jpg"width: 50height: 50
}
PropertyAnimation on x{target: ss //指明作用对象to:root.width - ss.widthduration: 3000running: root.running
}//还可以这样写
PropertyAnimation{target:ssproperty:"x" //指明属性to:root.width - ss.widthduration:3000runing:root.running
}
- 专门处理数值属性 - NumberAnimation
其实就是属性动画的特化版本
NumberAnimation on x{target: ssto:root.width - ss.widthduration: 3000running: root.running
}// 其实等同于
PropertyAnimation on x{target: ss //指明作用对象to:root.width - ss.widthduration: 3000running: root.running
}
- 专门处理颜色变化 - ColorAnimation
PropertyAnimation特化版
ColorAnimation {target: colorRectproperty: "color"from: "red"to: "blue"duration: 2000loops: Animation.Infiniterunning: true
}// 等同于
PropertyAnimation on color{target: colorRect //指明作用对象from: "red"to: "blue"duration: 2000loops: Animation.Infiniterunning: true
}
1.2、动画的触发方式
- 主要存在以下几种方式触发:
- 属性上的动画:在元素完全加载后自动运行
- 属性上的行为:属性值更改时自动运行
- 独立动画:使用
start()显示启动动画或将running设置为true时运行
- 属性上的动画:
在元素加载完成之后,立即自动运行,标志在于on
PropertyAnimation on color{target: colorRect //指明作用对象from: "red"to: "blue"duration: 2000loops: Animation.Infiniterunning: true
}
- 属性上的行为
当属性值发生变化时自动触发动画,标志在于behavior
// 行为动画:当x值改变时自动触发
Behavior on x {NumberAnimation {duration: 1000}}
- 独立动画
动画作为独立对象,需要通过代码进行显示启动- 调用
start() - 设置
running为true
- 调用
PropertyAnimation on color{id: color_animtarget: colorRect //指明作用对象from: "red"to: "blue"duration: 2000//注意此处没有设置running为true,不会自动触发
}Button {text: "running = true"onClicked: color_anim.running = true //手动控制
}
小结:
| 触发方式 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| 属性上的动画 | 页面加载动画、循环动画、不需要用户交互的动画 | 简单直接,自动运行 | 无法手动控制时机 |
| 属性上的行为 | 用户交互反馈、状态切换、属性绑定变化 | 自动响应属性变化 | 可能会在不希望的时机触发 |
| 独立动画 | 复杂动画序列,需要精确控制的动画 | 完全控制,可组合复杂动画 | 需要更多代码,手动进行管理 |
1.3、动画分组
- 分组有两种方式:
- 并行:将两组及以上动画同时执行
- 顺序:先执行完一个动画后,再执行另一个动画
- 并行动画
关键词:ParallelAnimation
ParallelAnimation{id:parallel_animrunning: true// 水平移动NumberAnimation{target: objectproperty: "x" //注意此时没使用onduration: 200}// 旋转动画RotationAnimation{target: objectproperty: "rotation"from: 0to: 360duration: 2000}
}
- 顺序动画
关键词SequentialAnimation
SequentialAnimation{id:sequent_animrunning: true// 先水平移动NumberAnimation{target: objectproperty: "x" //注意此时没使用onduration: 200}// 再旋转动画RotationAnimation{target: objectproperty: "rotation"from: 0to: 360duration: 2000}
}
二、缓动曲线(Easing Curves)
2.1、什么是缓动曲线
描述了动画过程中属性值随时间变化的速率。它决定了动画是匀速运动、加速运动、减速运动还是有弹性的运动。
基本概念:
- 线性(Linear): 匀速运动
- 缓入(Easeln):开始慢,然后加速
- 缓出(EaseOut): 开始快,然后减速
- 缓入缓出(EaseInOut): 开始和结束都慢,中间快
2.2、缓动曲线类型
主要是通过easing.type属性来设置
Behavior on scale{PropertyAnimation{duration:200easing.type:Easing.OutElastic}
}
QML提供曲线类型:
| 类型 | 说明 |
|---|---|
Easing.Linear | 线性变化,无加速减速 |
Easing.InQuad | 开始慢,然后加速 |
Easing.OutQuad | 开始快,然后减速 |
Easing.InOutQuad | 开始结束都慢,中间加速 |
Easing.OutInQuad | 开始结束都快,中间慢 |
Easing.InCubic | 立方缓入,比Quad更明显的加速 |
Easing.OutCubic | 立方缓出 |
Easing.InOutCubic | 立方缓入缓出 |
Easing.InElastic | 弹性效果,在开始时有回弹 |
Easing.OutElastic | 弹性效果,在结束时有回弹 |
Easing.InBack | 开始时稍微后退再前进 |
Easing.OutBack | 结束时超过目标值再退回 |
Easing.InOutBack | 开始和结束都有超过再退回的效果 |
Easing.InBounce | 弹跳效果,开始有弹跳 |
Easing.OutBounce | 弹跳效果,结束时有弹跳 |
Easing.InOutBounce | 开始和结束都有弹跳 |
2.3、自定义贝塞尔曲线
如果需要更精确的控制,可以使用自定义贝塞尔曲线:
PropertyAnimation {target: itemproperty: "x"to: 300duration: 1000easing.type: Easing.Beziereasing.bezierCurve: [0.68, -0.55, 0.265, 1.55] // 自定义贝塞尔控制点
}
注意:
缓动曲线虽然带线,但只强调运动轨迹,运动的速率,而不是真的画线—视觉上的线条
三、小测
场景:画一个油量表,类似进度条,超过20%时,显示绿色,低于20%时显示红色报警
import QtQuickItem {id: oil_width:parent.widthheight: parent.height// 油量属性, 范围0-100property real fuelLevel: 75property color normalColor: "#00ff00"property color warnningColor: "#ff0000"property real warningValue: 20 // 警告阈值property int autoChangeDirection: -1 //自动改变方向Rectangle{id:backgroundanchors.fill: parentcolor:"#2d2d2d"radius: 10}Column{anchors.fill: parentanchors.margins: 10spacing: 5Row{width:parent.widthheight: 20Text{text:"E"color:"white"font.pixelSize: 16font.bold: true}Item{width: parent.width - 40height: 1}Text{text:"F"color: "white"font.pixelSize: 16font.bold: true}}Rectangle{width: parent.widthheight: 25radius: 15// 进度条Rectangle{id:progressBarwidth: (fuelLevel / 100) * parent.widthheight: parent.heightradius: parent.radiuscolor:fuelLevel <= warningValue ? warnningColor : normalColor// 渐变效果gradient: Gradient{GradientStop{position: 0.0color: Qt.lighter(progressBar.color, 1.2)}GradientStop{position: 1.0color: Qt.darker(progressBar.color, 1.2)}}// 属性值动画Behavior on width{NumberAnimation{duration: 500easing.type: Easing.OutCubic}}// 颜色动画Behavior on color{ColorAnimation {duration: 300}}}// 油量显示Text{id:fuelTextanchors.horizontalCenter: parent.horizontalCentertext:fuelLevel.toFixed(1) + "%"color: fuelLevel <= warningValue ? warnningColor : normalColorfont.pixelSize: 16font.bold: trueBehavior on color{ColorAnimation {duration: 300}}}}}Timer{id: autoChangeTimerinterval: 200running: truerepeat:trueonTriggered: {//更新油量值fuelLevel += autoChangeDirection * 0.5if(fuelLevel >= 100){fuelLevel = 100autoChangeDirection = -1}else if (fuelLevel <= 0){fuelLevel = 0autoChangeDirection = 1}}}
}

