QML 动画效果详解

发布于:2025-07-20 ⋅ 阅读:(19) ⋅ 点赞:(0)

属性动画(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
    }
}

特点与优势

  1. 简洁性​:不需要指定target和property,代码更简洁
  2. 自动绑定​:动画自动绑定到声明它的元素的对应属性
  3. 自动运行​:这种形式的动画会在组件加载完成后自动开始运行
  4. 适用于任何属性​:可以对任何支持动画的属性使用此语法

实际应用案例

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 }
    }
}

注意事项

  1. 初始化赋值不会触发​:组件创建时的初始设定不会触发Behavior动画
  2. 性能考虑​:不要对大量快速变化的属性绑定耗时动画
  3. 多重Behavior​:一个属性只能有一个Behavior,但可以在内部使用ParallelAnimation/SequentialAnimation
  4. 与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 }
}

注意事项

  1. 动画控制​:子动画的running属性会被容器动画控制,不应单独设置
  2. 持续时间​:ParallelAnimation的持续时间等于最长子动画的持续时间
  3. 性能考虑​:复杂的动画组合可能需要更多的CPU资源
  4. 调试技巧​:可以在动画的running和completed信号中添加console.log跟踪动画状态

ParallelAnimation和SequentialAnimation为QML动画提供了强大的组合能力,通过它们的嵌套和组合,可以构建出几乎任何复杂的动画序列,满足现代UI对动画效果的各类需求。

动画师动画(Animator)

Animator是Qt Quick 2.2及以上版本引入的一种特殊动画类型,与常规动画不同,Animator直接在Qt Quick的场景图渲染线程中执行,即使在UI线程繁忙时也能保持流畅的动画效果。

核心优势

  1. 独立于UI线程​:在UI线程阻塞时仍能流畅运行
  2. 高性能​:直接在渲染线程执行,减少中间步骤
  3. 专有类型​:针对特定属性优化的动画类型
  4. 简单易用​:语法与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元素来实现精灵动画。

核心组件

  1. SpriteSequence​:精灵动画的容器,管理多个Sprite动画
  2. Sprite​:定义单个动画序列
  3. 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属性定义状态转换:

  1. 随机转换​:根据权重随机切换到其他动画
  2. 强制转换​:通过设置goalSprite强制切换到指定动画
  3. 直接跳转​:使用jumpTo()方法立即切换到指定动画

使用场景

  1. 游戏角色动画(行走、奔跑、跳跃等)
  2. 复杂的状态转换动画
  3. 需要随机或条件触发动画变化的场景
  4. 基于精灵图的动画效果

精灵动画特别适合游戏开发和需要复杂动画序列的应用,它能够有效地组织和管理多个动画状态,并通过状态转换创建丰富的交互体验。

动态精灵动画(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
复杂度 简单 复杂
动画数量 单一动画 多动画序列
状态转换 不支持 支持
性能 更高 略低
适用场景 简单帧动画 复杂动画状态机

​性能优化建议

  1. 使用精灵图集​:将多帧打包到一个图像文件中,减少资源加载开销
  2. 合理设置帧率​:根据实际需要设置,避免不必要的渲染
  3. 适时暂停​:当动画不可见时暂停播放
  4. 预加载资源​:提前加载动画资源,避免运行时卡顿
  5. 减少插值​:对于像素艺术风格动画,关闭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提供了多种边界行为控制方式:

  1. StopAtBounds​(默认):内容不能拖动到边界之外,轻拂也不会超调
  2. DragOverBounds​:内容可以拖动到边界之外,但轻拂不会超调
  3. OvershootBounds​:轻拂时可以超过边界,但不能拖动到边界之外
  4. DragAndOvershootBounds​:内容可以拖动到边界之外,轻拂时也可以超过边界

性能优化技巧

  1. 设置clip属性​:对于非全屏Flickable,应将clip设为true以避免渲染开销
  2. 合理使用pixelAligned​:对于像素精确的内容,启用pixelAligned可避免亚像素渲染
  3. 动态加载内容​:对于超长列表,考虑使用动态加载技术
  4. 避免过度绘制​:优化内容项的绘制逻辑

翻转效果(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
            }
        }
    }
}

 

性能优化建议

  1. 简化内容​:Flipable的两面内容应尽量简单,避免复杂嵌套
  2. 合理使用Perspective​:在父元素上设置Perspective变换可增强3D效果
  3. 避免频繁切换​:翻转动画较耗资源,不宜频繁触发
  4. 预渲染内容​:对于复杂内容,考虑使用ShaderEffect预渲染

总结

QML提供了丰富而强大的动画系统,从基础的属性动画到复杂的3D效果,开发者可以创建各种流畅的交互体验。关键要点包括:

  1. 选择合适的动画类型​:根据场景选择PropertyAnimation、Behavior或Animator
  2. 组合使用动画​:利用ParallelAnimation和SequentialAnimation创建复杂序列
  3. 性能优化​:对于频繁触发的动画,优先考虑Animator类型
  4. 状态管理​:合理使用State和Transition管理界面状态变化

网站公告

今日签到

点亮在社区的每一天
去签到