属性动画(PropertyAnimation)
PropertyAnimation是QML中最基础、最常用的动画类型,它可以对任何基于数字或颜色的属性进行动画化处理,实现平滑的过渡效果。
核心属性与用法
PropertyAnimation的主要属性如下表所示:
属性 | 类型 | 描述 | 默认值 |
---|---|---|---|
target |
QtObject | 动画作用的目标对象 | 父对象 |
property |
string | 要动画化的属性名 | 必须指定 |
from |
variant | 动画起始值 | 当前属性值 |
to |
variant | 动画结束值 | 必须指定 |
duration |
int | 动画持续时间(ms) | 250 |
easing.type |
enumeration | 缓动曲线类型 | Easing.Linear |
easing.amplitude |
real | 弹性动画幅度 | 1.0 |
easing.period |
real | 弹性动画周期 | 0.3 |
loops |
int | 循环次数 | 1 |
running |
bool | 是否自动运行 | false |
alwaysRunToEnd |
bool | 停止时是否完成动画 | false |
基础示例
import QtQuick 2.15
Rectangle {
id: rect
width: 100; height: 100
color: "red"
x: 0
// 基本属性动画
PropertyAnimation {
target: rect
property: "x"
to: 200
duration: 1000
running: true
}
}
缓动曲线示例
PropertyAnimation支持多种缓动曲线,可以创建更自然的动画效果:
PropertyAnimation {
property: "rotation"
to: 360
easing.type: Easing.OutBounce
easing.amplitude: 2.0
duration: 1000
}
相对值动画
PropertyAnimation支持相对当前值的动画:
PropertyAnimation {
property: "x"
to: myItem.x + 50 // 相对当前位置移动50像素
duration: 500
}
多属性动画
可以同时对多个属性应用动画:
ParallelAnimation {
PropertyAnimation { property: "x"; to: 100 }
PropertyAnimation { property: "y"; to: 100 }
PropertyAnimation { property: "opacity"; to: 0.5 }
}
PropertyAnimation的强大之处在于它的通用性,几乎可以对任何QML元素的任何属性进行动画处理,是构建动态UI的基础。
数字动画(NumberAnimation)
NumberAnimation是PropertyAnimation的派生类,专门用于处理数值类型的属性动画,如位置、大小、旋转角度等。
核心属性
NumberAnimation继承了PropertyAnimation的所有属性,并特别优化了对数值类型的处理:
属性 | 类型 | 描述 | 默认值 |
---|---|---|---|
from |
real | 动画起始值 | 当前属性值 |
to |
real | 动画结束值 | 必须指定 |
by |
real | 相对变化量 | - |
其他属性继承自PropertyAnimation |
基本用法示例
import QtQuick 2.0
Rectangle {
width: 100; height: 100
color: "red"
// 数字动画作为属性值源
NumberAnimation on x {
to: 50
duration: 1000
}
}
三种写法对比
NumberAnimation有三种主要使用方式:
方法1:直接绑定属性
NumberAnimation on rotation {
id: minutePinAni
from: 0
to: 360
duration: 20000
loops: Animation.Infinite
}
方法2:独立动画对象
NumberAnimation {
id: minutePinAni
target: minPin
property: "rotation"
to: 360
duration: 10000
loops: Animation.Infinite
}
方法3:通过Behavior
Behavior on rotation {
NumberAnimation {
from: 0
to: 100
duration: 20000
loops: Animation.Infinite
}
}
与RotationAnimation的区别
虽然NumberAnimation可以用于旋转动画,但QML提供了专门的RotationAnimation类型,它比NumberAnimation多了一个旋转方向属性:
RotationAnimation {
target: item
property: "rotation"
direction: RotationAnimation.Clockwise // 顺时针方向
from: 0
to: 360
duration: 1000
}
RotationAnimation的direction
属性可以是:
RotationAnimation.Numerical
(默认):数值线性插值RotationAnimation.Clockwise
:顺时针旋转RotationAnimation.Counterclockwise
:逆时针旋转RotationAnimation.Shortest
:沿最短路径旋转
NumberAnimation因其简单高效,在大多数数值动画场景中都是首选方案,特别是当需要精确控制数值变化过程时。
预定义的目标和属性动画
QML提供了一种更简洁的语法来定义属性动画,即直接在属性上声明动画,这种方式称为"预定义的目标和属性动画"或"on语法"。
基本语法
<AnimationType> on <property> {
// 动画属性设置
}
典型示例
import QtQuick 2.0
Rectangle {
id: rect
width: 100; height: 100
color: "red"
// 预定义x属性的动画
PropertyAnimation on x {
to: 100
duration: 500
}
// 预定义y属性的动画
PropertyAnimation on y {
to: 100
duration: 500
}
}
特点与优势
- 简洁性:不需要指定target和property,代码更简洁
- 自动绑定:动画自动绑定到声明它的元素的对应属性
- 自动运行:这种形式的动画会在组件加载完成后自动开始运行
- 适用于任何属性:可以对任何支持动画的属性使用此语法
实际应用案例
import QtQuick 2.15
Rectangle {
width: 200
height: 200
anchors.centerIn: parent
color: "lightgreen"
// 旋转动画
RotationAnimation on rotation {
from: 0
to: 360
duration: 2000
loops: Animation.Infinite
}
// 缩放动画
ScaleAnimator on scale {
from: 0.5
to: 1.5
duration: 1000
loops: Animation.Infinite
}
// 透明度动画
OpacityAnimator on opacity {
from: 0.3
to: 1.0
duration: 1500
loops: Animation.Infinite
}
}
与独立动画的对比
相比于独立的动画声明,预定义语法有以下区别:
特性 | 预定义语法 | 独立动画 |
---|---|---|
目标对象 | 隐含(父元素) | 需显式指定 |
属性绑定 | 自动关联 | 需显式指定 |
执行时机 | 自动开始 | 需手动启动或设置running |
复用性 | 较低 | 较高 |
代码量 | 较少 | 较多 |
预定义的目标和属性动画语法非常适合那些简单、直接的动画需求,特别是在原型设计或简单动画场景中,可以显著减少代码量并提高可读性。
过渡动画(Transition)
Transition用于定义状态变化时的动画效果,它可以在元素从一个状态切换到另一个状态时,自动应用指定的动画。
核心属性
Transition的主要属性如下:
属性 | 类型 | 描述 | 默认值 |
---|---|---|---|
from |
string | 起始状态名 | "" (任何状态) |
to |
string | 目标状态名 | "" (任何状态) |
reversible |
bool | 是否可反向播放 | false |
enabled |
bool | 是否启用过渡 | true |
animations |
list | 动画列表 | 空列表 |
基本用法
import QtQuick 2.15
Rectangle {
id: myRect
width: 100; height: 100
color: "red"
state: "state1"
MouseArea {
anchors.fill: parent
onPressed: myRect.state = "state2"
onReleased: myRect.state = "state1"
}
states: [
State {
name: "state1"
PropertyChanges { target: myRect; x: 0; y: 0 }
},
State {
name: "state2"
PropertyChanges { target: myRect; x: 100; y: 100 }
}
]
transitions: [
Transition {
from: "state1"
to: "state2"
NumberAnimation { properties: "x,y"; duration: 500 }
},
Transition {
from: "state2"
to: "state1"
NumberAnimation { properties: "x,y"; duration: 300 }
}
]
}
多属性过渡示例
transitions: Transition {
// 颜色过渡
ColorAnimation { duration: 1000 }
// 位置过渡
NumberAnimation {
properties: "x,y"
duration: 500
easing.type: Easing.OutBack
}
// 旋转过渡
RotationAnimation {
duration: 700
direction: RotationAnimation.Clockwise
}
}
高级用法:条件过渡
可以根据不同条件应用不同的过渡效果:
transitions: [
Transition {
from: "*"; to: "dragging"
NumberAnimation { property: "scale"; to: 1.2; duration: 200 }
},
Transition {
from: "dragging"; to: "*"
SequentialAnimation {
NumberAnimation { property: "scale"; to: 1.0; duration: 200 }
SpringAnimation { property: "rotation"; spring: 2; damping: 0.2 }
}
}
]
与Behavior的区别
Transition和Behavior都用于属性变化时的动画,但有以下区别:
特性 | Transition | Behavior |
---|---|---|
触发条件 | 状态变化 | 任何属性变化 |
作用范围 | 状态切换期间 | 始终有效 |
控制粒度 | 基于状态 | 基于属性 |
适用场景 | 明确的状态机 | 持续性的属性变化 |
Transition在创建有明确状态划分的界面时非常有用,如折叠/展开、激活/非激活等场景,能够提供清晰的视觉反馈和状态转换指示。
默认行为动画(Behavior)
Behavior是QML中用于对属性值变化做隐式动画的机制,它绑定到某个属性上,当该属性在运行时被修改时,会自动触发预定义的动画效果。
核心属性
Behavior的主要属性如下:
属性 | 类型 | 描述 | 默认值 |
---|---|---|---|
animation |
Animation | 属性变化时应用的动画 | 必须指定 |
enabled |
bool | 是否启用行为动画 | true |
基本语法
Behavior on <property> {
<animation>
}
基础示例
import QtQuick 2.15
Rectangle {
width: 100; height: 100
color: "red"
// 为x坐标变化添加行为动画
Behavior on x {
NumberAnimation { duration: 500 }
}
MouseArea {
anchors.fill: parent
onClicked: parent.x = parent.x + 50
}
}
常见内置Animation类型
Behavior可以与多种动画类型配合使用:
类型 | 可动画化属性 | 说明 |
---|---|---|
NumberAnimation |
数值型(x, y, width...) | 通过线性或缓动曲线插值数值 |
ColorAnimation |
color, border.color... | 在两个颜色值之间渐变 |
RotationAnimation |
rotation | 对旋转角度做插值动画 |
ScaleAnimation |
scale | 对缩放因子做插值 |
SpringAnimation |
任意数值型 | 弹簧阻尼动画,带回弹效果 |
SmoothedAnimation |
任意数值型 | 平滑快速跟随目标值 |
组合多个动画
Behavior内部可以使用组合动画实现复杂效果:
Behavior on width {
SequentialAnimation {
NumberAnimation { duration: 300; easing.type: Easing.OutQuad }
PauseAnimation { duration: 100 }
NumberAnimation { duration: 200; easing.type: Easing.InQuad }
}
}
条件性行为
可以动态启用或禁用Behavior:
Rectangle {
id: rect
property bool animationsEnabled: true
Behavior on x {
enabled: rect.animationsEnabled
NumberAnimation { duration: 200 }
}
}
注意事项
- 初始化赋值不会触发:组件创建时的初始设定不会触发Behavior动画
- 性能考虑:不要对大量快速变化的属性绑定耗时动画
- 多重Behavior:一个属性只能有一个Behavior,但可以在内部使用ParallelAnimation/SequentialAnimation
- 与visible属性:对visible属性直接应用Behavior无效,可以改为对opacity应用动画然后绑定visible到opacity > 0
Behavior的主要优势在于它能够降低动画调用成本,无需在每次更改时手动启动动画,只需在组件声明里一次性配置,后续所有对该属性的改变都会平滑地过渡。
并行动画与序列动画(ParallelAnimation和SequentialAnimation)
QML提供了两种组合动画的方式:ParallelAnimation(并行动画)和SequentialAnimation(序列动画),它们作为容器可以嵌套其他动画元素,实现复杂的动画效果。
ParallelAnimation(并行动画)
ParallelAnimation允许所有子动画同时运行,适用于需要多个属性同步动画的场景。
核心属性
属性 | 类型 | 描述 | 默认值 |
---|---|---|---|
animations |
list | 子动画列表 | 空列表 |
running |
bool | 是否运行 | false |
loops |
int | 循环次数 | 1 |
alwaysRunToEnd |
bool | 停止时是否完成当前动画 | false |
基本示例
import QtQuick 2.15
Rectangle {
id: rect
width: 100; height: 100
color: "red"
x: 0; y: 0; opacity: 1.0
ParallelAnimation {
running: true
NumberAnimation { target: rect; property: "x"; to: 200; duration: 1000 }
NumberAnimation { target: rect; property: "y"; to: 200; duration: 1500 }
PropertyAnimation { target: rect; property: "opacity"; to: 0.5; duration: 800 }
}
}
动态添加动画
ParallelAnimation支持动态添加子动画:
ParallelAnimation {
id: dynamicAnim
}
function addScaleAnimation() {
var anim = Qt.createQmlObject('import QtQuick 2.15; NumberAnimation {
property: "scale";
to: 2.0;
duration: 500
}', dynamicAnim);
dynamicAnim.addAnimation(anim);
}
SequentialAnimation(序列动画)
SequentialAnimation按顺序依次运行子动画,适用于需要多个动画按特定顺序执行的场景。
核心属性
属性 | 类型 | 描述 | 默认值 |
---|---|---|---|
animations |
list | 子动画列表 | 空列表 |
running |
bool | 是否运行 | false |
loops |
int | 循环次数 | 1 |
alwaysRunToEnd |
bool | 停止时是否完成当前动画 | false |
currentAnimation |
Animation | 当前正在运行的子动画 | null |
基本示例
import QtQuick 2.15
Rectangle {
id: rect
width: 100; height: 100
color: "red"
x: 0; y: 0
SequentialAnimation {
running: true
NumberAnimation { target: rect; property: "y"; to: 200; duration: 1000 }
ColorAnimation { target: rect; property: "color"; to: "blue"; duration: 500 }
RotationAnimation { target: rect; property: "rotation"; to: 360; duration: 800 }
}
}
组合动画序列
可以嵌套ParallelAnimation和SequentialAnimation创建复杂动画:
SequentialAnimation {
// 第一阶段:并行移动和旋转
ParallelAnimation {
NumberAnimation { property: "x"; to: 200 }
RotationAnimation { target: rotation; to: 90 }
}
// 第二阶段:并行改变颜色和大小
ParallelAnimation {
ColorAnimation { property: "color"; to: "blue" }
NumberAnimation { property: "width"; to: 150 }
}
// 第三阶段:暂停后恢复
PauseAnimation { duration: 500 }
NumberAnimation { property: "scale"; to: 1.0; duration: 300 }
}
注意事项
- 动画控制:子动画的running属性会被容器动画控制,不应单独设置
- 持续时间:ParallelAnimation的持续时间等于最长子动画的持续时间
- 性能考虑:复杂的动画组合可能需要更多的CPU资源
- 调试技巧:可以在动画的running和completed信号中添加console.log跟踪动画状态
ParallelAnimation和SequentialAnimation为QML动画提供了强大的组合能力,通过它们的嵌套和组合,可以构建出几乎任何复杂的动画序列,满足现代UI对动画效果的各类需求。
动画师动画(Animator)
Animator是Qt Quick 2.2及以上版本引入的一种特殊动画类型,与常规动画不同,Animator直接在Qt Quick的场景图渲染线程中执行,即使在UI线程繁忙时也能保持流畅的动画效果。
核心优势
- 独立于UI线程:在UI线程阻塞时仍能流畅运行
- 高性能:直接在渲染线程执行,减少中间步骤
- 专有类型:针对特定属性优化的动画类型
- 简单易用:语法与PropertyAnimation类似
Animator类型
QML提供了多种专门的Animator类型:
类型 | 作用属性 | 描述 |
---|---|---|
XAnimator |
x | 水平位置动画 |
YAnimator |
y | 垂直位置动画 |
ScaleAnimator |
scale | 缩放动画 |
RotationAnimator |
rotation | 旋转动画 |
OpacityAnimator |
opacity | 透明度动画 |
UniformAnimator |
uniform | 着色器统一变量动画 |
基本用法
import QtQuick
Rectangle {
id: rect1
width: 100
height: 100
x: 10
y: 10
color: "red"
XAnimator on x {
from: 10
to: 300
duration: 2000
loops: Animator.Infinite
}
YAnimator on y {
from: 10
to: 300
duration: 2000
loops: Animator.Infinite
}
ScaleAnimator on scale {
from: 0.1
to: 1.5
duration: 2000
loops: Animator.Infinite
}
OpacityAnimator on opacity {
from: 0.1
to: 1.0
duration: 2000
loops: Animator.Infinite
}
RotationAnimator on rotation {
from: 0
to: 360
duration: 2000
loops: Animator.Infinite
}
}
与PropertyAnimation的对比
特性 | Animator | PropertyAnimation |
---|---|---|
执行线程 | 渲染线程 | UI线程 |
UI阻塞时 | 继续运行 | 可能卡顿 |
适用版本 | Qt Quick 2.2+ | 所有版本 |
性能 | 更高 | 一般 |
属性支持 | 特定属性 | 所有属性 |
适用场景 | 高性能需求 | 通用需求 |
Animator类型特别适合那些需要高性能、流畅动画的场景,特别是在UI线程可能有繁重任务时,使用Animator可以确保动画不受影响,保持流畅运行。
精灵动画(SpriteAnimations)--嵌入式使用较少,了解就好
精灵动画是游戏开发和交互式应用中常见的技术,通过快速连续显示一系列图像帧来创建动画效果。QML提供了SpriteSequence和Sprite元素来实现精灵动画。
核心组件
- SpriteSequence:精灵动画的容器,管理多个Sprite动画
- Sprite:定义单个动画序列
- AnimatedSprite:简化版的单动画精灵(后面详细介绍)
SpriteSequence属性
属性 | 类型 | 描述 | 默认值 |
---|---|---|---|
currentSprite |
string | 当前精灵动画的名称 | "" |
goalSprite |
string | 目标精灵动画 | "" |
interpolate |
bool | 是否开启插值运算 | true |
running |
bool | 是否执行动画 | true |
sprites |
list | 精灵动画集合 | 空列表 |
Sprite属性
属性 | 类型 | 描述 |
---|---|---|
name |
string | 动画名称 |
source |
url | 精灵图片源 |
frameX |
int | 起始帧的x坐标 |
frameY |
int | 起始帧的y坐标 |
frameCount |
int | 动画帧数 |
frameWidth |
int | 单帧宽度 |
frameHeight |
int | 单帧高度 |
frameDuration |
int | 每帧持续时间(ms) |
to |
map | 过渡到其他动画的名称和权重 |
基本示例
import QtQuick
Window {
width: 640
height: 900
visible: true
title: qsTr("Hello World")
MouseArea {
anchors.fill: parent
onClicked: {
animation.start()
}
}
SequentialAnimation {
id: animation
//脚本会在前一个动画结束后、下一个动画开始前执行
//goalSprite属性可以指定目标Sprite类型,指定该属性后会无视过渡权重,而以最短的路径到达目标动画。即从still->blink->floating->flailing->falling这个顺序播放动画
ScriptAction {
script: image.goalSprite = "falling";
}
NumberAnimation {
target: image
property: "y"
to: 500
duration: 12000
}
// 下降完成之后回到still动画
ScriptAction {
script: {
image.goalSprite = "";
image.jumpTo("still")
}
}
PropertyAction {
target: image
property: "y"
value: 0
}
}
//精灵动画的容器,管理多个Sprite动画
SpriteSequence {
id: image
width: 256
height: 256
anchors.horizontalCenter: parent.horizontalCenter
interpolate: false
goalSprite: "" //最终动画
// 权重的作用原理
// 数值含义:to对象中的键值对(如"still":1)表示从当前动画切换到其他动画的相对概率。
// 例如,"still":1, "blink":0.1表示:
// 切换到still动画的概率是 1/(1+0.1) ≈ 90.9%
// 切换到blink动画的概率是 0.1/(1+0.1) ≈ 9.1%
// 权重为0:如"floating":0表示禁止切换到该动画
// 行为表现:动画播放时,系统会按权重比例随机选择下一状态,still动画有极高概率保持,偶尔触发blink,而不会切换到floating
// 静止
Sprite {
name: "still"
source: "BearSheet.png"
frameCount: 1 //帧数
frameWidth: 256 //帧的宽度和高度
frameHeight: 256
frameDuration: 100 //持续时间
to: {
"still": 1, //1代表权重
"blink": 0.1,
"floating": 0
}
}
// 眨眼
Sprite {
name: "blink"
source: "BearSheet.png"
frameCount: 3
frameX: 256
frameY: 1536
frameWidth: 256
frameHeight: 256
frameDuration: 100
to: {
"still": 1
}
}
// 漂浮
Sprite {
name: "floating"
source: "BearSheet.png"
frameCount: 9
frameX: 0
frameY: 0
frameWidth: 256
frameHeight: 256
frameDuration: 160
to: {
"still": 0,
"flailing": 1
}
}
// 摆动
Sprite {
name: "flailing"
source: "BearSheet.png"
frameCount: 8
frameX: 0
frameY: 768
frameWidth: 256
frameHeight: 256
frameDuration: 160
to: {
"falling": 1
}
}
// 下降
Sprite {
name: "falling"
source: "BearSheet.png"
frameCount: 5
frameY: 1280
frameWidth: 256
frameHeight: 256
frameDuration: 160
to: {
"falling": 1
}
}
}
}
效果:
动画过渡机制
SpriteSequence中的动画可以通过to
属性定义状态转换:
- 随机转换:根据权重随机切换到其他动画
- 强制转换:通过设置
goalSprite
强制切换到指定动画 - 直接跳转:使用
jumpTo()
方法立即切换到指定动画
使用场景
- 游戏角色动画(行走、奔跑、跳跃等)
- 复杂的状态转换动画
- 需要随机或条件触发动画变化的场景
- 基于精灵图的动画效果
精灵动画特别适合游戏开发和需要复杂动画序列的应用,它能够有效地组织和管理多个动画状态,并通过状态转换创建丰富的交互体验。
动态精灵动画(AnimatedSprite)--嵌入式使用较少,了解就好
AnimatedSprite是QML中用于实现帧动画的简化组件,适用于不需要复杂状态管理的单一动画序列。
核心属性
AnimatedSprite的主要属性如下:
属性 | 类型 | 描述 | 默认值 |
---|---|---|---|
frameCount |
int | 动画总帧数 | 1 |
frameRate |
real | 每秒播放帧数 | - |
frameWidth |
int | 单帧图像宽度 | 元素宽度 |
frameHeight |
int | 单帧图像高度 | 元素高度 |
source |
url | 精灵图集路径 | 必须指定 |
loops |
int | 循环次数 | Animation.Infinite |
currentFrame |
int | 当前帧索引 | 0 |
frameDuration |
int | 每帧持续时间(ms) | - |
frameSync |
bool | 是否同步显示刷新率 | false |
interpolate |
bool | 是否在帧间插值 | true |
paused |
bool | 是否暂停 | false |
reverse |
bool | 是否反向播放 | false |
running |
bool | 是否运行 | true |
基本用法
import QtQuick 2.12
import QtQuick.Window 2.12
Window {
visible: true
width: 800
height: 600
color: "black"
title: "Qt基于Qml图像帧动画播放"
AnimatedSprite {
id: animated
width: 365
height: 365
anchors.centerIn: parent
source: "qrc:/numbers.png"
frameWidth: 64
frameHeight: 64
frameDuration: 1000 // 每秒播放一帧
frameCount: 10
frameX: 0
frameY: 0
onCurrentFrameChanged: {
info.text = "%1/%2".arg(animated.currentFrame).arg(animated.frameCount)
}
}
// 控制界面
Row {
spacing: 20
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.bottomMargin: 4
Text {
id: info
width: 120
height: 60
color: "red"
font.pixelSize: 38
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignRight
}
Button {
width: 120
height: 60
text: (animated.paused === true) ? "播放" : "暂停"
onClicked: (animated.paused === true) ? animated.resume() : animated.pause()
}
Button {
width: 120
height: 60
text: "单帧播放"
onClicked: animated.advance()
}
Button {
width: 120
height: 60
text: "重置"
onClicked: animated.restart()
}
}
}
与SpriteSequence的对比
特性 | AnimatedSprite | SpriteSequence |
---|---|---|
复杂度 | 简单 | 复杂 |
动画数量 | 单一动画 | 多动画序列 |
状态转换 | 不支持 | 支持 |
性能 | 更高 | 略低 |
适用场景 | 简单帧动画 | 复杂动画状态机 |
性能优化建议
- 使用精灵图集:将多帧打包到一个图像文件中,减少资源加载开销
- 合理设置帧率:根据实际需要设置,避免不必要的渲染
- 适时暂停:当动画不可见时暂停播放
- 预加载资源:提前加载动画资源,避免运行时卡顿
- 减少插值:对于像素艺术风格动画,关闭interpolate属性
AnimatedSprite因其简单易用和高效性能,成为实现简单帧动画的首选方案,特别适合游戏特效、加载动画、简单角色动画等场景。
弹动效果(Flickable)
Flickable是Qt Quick中用于实现可拖动和弹动效果的元素,它提供了一个可以滚动的区域,用户可以通过滑动手势浏览超出显示区域的内容。
核心属性
Flickable的主要属性如下:
属性 | 类型 | 描述 | 默认值 |
---|---|---|---|
contentWidth |
real | 内容宽度 | 必须指定 |
contentHeight |
real | 内容高度 | 必须指定 |
contentX |
real | 当前水平位置 | 0 |
contentY |
real | 当前垂直位置 | 0 |
flickableDirection |
enum | 滑动方向(Flickable.AutoFlickDirection等) | AutoFlickDirection |
boundsBehavior |
enum | 边界行为(Flickable.StopAtBounds等) | StopAtBounds |
maximumFlickVelocity |
real | 最大滑动速度(像素/秒) | 平台相关 |
flickDeceleration |
real | 滑动减速度 | 平台相关 |
interactive |
bool | 是否允许用户交互 | true |
pixelAligned |
bool | 是否像素对齐 | false |
pressDelay |
int | 按下延迟时间(ms) | 0 |
基本用法
import QtQuick 2.5
import QtQuick.Window 2.2
Window {
visible: true
width: 640
height: 480
title: qsTr("Flickable Demo")
Flickable {
id: flickable
interactive: true
anchors.fill: parent
contentWidth: 1000
contentHeight: 1000
boundsBehavior: Flickable.StopAtBounds
// 内容项 - 一个大图像
Image {
id: image
source: "kun.jpg"
width: 1000
height: 1000
}
}
// 添加滚动条指示
ScrollBar {
id: vbar
width: 12
height: flickable.height
anchors.right: flickable.right
orientation: Qt.Vertical
position: flickable.visibleArea.yPosition
size : flickable.visibleArea.heightRatio
onPositionChanged: {
if (active) flickable.contentY = position * (flickable.contentHeight );
}
}
ScrollBar {
id: hbar
width: flickable.width
height: 12
anchors.bottom: flickable.bottom
orientation: Qt.Horizontal
position: flickable.visibleArea.xPosition
size : flickable.visibleArea.widthRatio
onPositionChanged: {
if (active) flickable.contentX = position * (flickable.contentWidth );
}
}
}
动态内容示例
Flickable常用于显示动态生成的内容:
Flickable {
anchors.fill: parent
contentWidth: col.width
contentHeight: col.height
Column {
id: col
width: parent.width
Repeater {
model: 50
delegate: Rectangle {
width: col.width
height: 60
color: index % 2 ? "lightgray" : "white"
Text {
text: "Item " + index
font.pixelSize: 20
anchors.centerIn: parent
}
}
}
}
}
高级用法:自定义回弹效果
Flickable的rebound
属性允许开发者自定义内容回弹到边界时的过渡动画效果:
Flickable {
width: 200; height: 200
contentWidth: 400; contentHeight: 400
boundsBehavior: Flickable.DragOverBounds
rebound: Transition {
NumberAnimation {
properties: "x,y"
duration: 1000
easing.type: Easing.OutBounce
}
}
Rectangle {
width: 400; height: 400
gradient: Gradient {
GradientStop { position: 0.0; color: "lightsteelblue" }
GradientStop { position: 1.0; color: "blue" }
}
}
}
边界行为详解
Flickable提供了多种边界行为控制方式:
- StopAtBounds(默认):内容不能拖动到边界之外,轻拂也不会超调
- DragOverBounds:内容可以拖动到边界之外,但轻拂不会超调
- OvershootBounds:轻拂时可以超过边界,但不能拖动到边界之外
- DragAndOvershootBounds:内容可以拖动到边界之外,轻拂时也可以超过边界
性能优化技巧
- 设置clip属性:对于非全屏Flickable,应将
clip
设为true以避免渲染开销 - 合理使用pixelAligned:对于像素精确的内容,启用
pixelAligned
可避免亚像素渲染 - 动态加载内容:对于超长列表,考虑使用动态加载技术
- 避免过度绘制:优化内容项的绘制逻辑
翻转效果(Flipable)
Flipable是QML中用于实现3D翻转效果的元素,可以创建卡片翻转、面板切换等视觉效果。
核心属性
属性 | 类型 | 描述 | 默认值 |
---|---|---|---|
front |
Item | 正面显示的项 | 必须指定 |
back |
Item | 背面显示的项 | 可选 |
side |
enumeration | 当前显示的面(Front或Back) | Front |
transform |
list | 应用的变换列表 | 空列表 |
axis |
vector3d | 旋转轴(x,y,z) | (0,1,0) |
angle |
real | 当前旋转角度(度) | 0 |
基本用法
import QtQuick
Window {
width: 640
height: 480
visible: true
title: qsTr("Hello World")
Flipable {
id: flipable
width: 240
height: 240
anchors.centerIn: parent
property bool flipped: falsed
front: Image {
source: "front.png"
anchors.centerIn: parent
}
back: Image {
source: "back.png"
anchors.centerIn: parent
}
transform: Rotation {
id: rotation
origin.x: flipable.width / 2
origin.y: flipable.height / 2
axis.x: 0
axis.y: 1
axis.z: 0
angle: 0
}
states: State {
name: "back"
when: flipable.flipped
PropertyChanges {
target: rotation
angle: 180
}
}
transitions: Transition {
NumberAnimation {
target: rotation
property: "angle"
duration: 500
}
}
MouseArea {
anchors.fill: parent
onClicked: {
flipable.flipped = !flipable.flipped
}
}
}
}
性能优化建议
- 简化内容:Flipable的两面内容应尽量简单,避免复杂嵌套
- 合理使用Perspective:在父元素上设置
Perspective
变换可增强3D效果 - 避免频繁切换:翻转动画较耗资源,不宜频繁触发
- 预渲染内容:对于复杂内容,考虑使用
ShaderEffect
预渲染
总结
QML提供了丰富而强大的动画系统,从基础的属性动画到复杂的3D效果,开发者可以创建各种流畅的交互体验。关键要点包括:
- 选择合适的动画类型:根据场景选择PropertyAnimation、Behavior或Animator
- 组合使用动画:利用ParallelAnimation和SequentialAnimation创建复杂序列
- 性能优化:对于频繁触发的动画,优先考虑Animator类型
- 状态管理:合理使用State和Transition管理界面状态变化