QML-动画

一、QML中的动画

1.1、动画类型

  • 在QML中存在多种动画类型:
    • PropertyAnimation: 属性值改变播放动画--通用类型
    • NumberAnimation:qreal-type值改变播放动画
    • ColorAnimation:颜色值改变播放动画
    • RotationAnimation:旋转值改变播放动画
    • OpacityAnimation: 渐变透明
  • 属性值改变播放的动画-PropertyAnimation
    最通用的动画类型,可以动画任何属性。
javascript 复制代码
import QtQuick

Image{
          id: root
          source: "qrc:/image/bgd.jpg"
          anchors.fill: parent

          property int  padding: 40
          property bool running: false

          // 资源加载状态检查
          onStatusChanged: {
                    if(status === Image.Error){
                              console.log("背景图片加载失败:", source)
                    }else if(status === Image.Ready){
                              console.log("背景图片加载成果...")
                    }
          }

          Image{
                    id:ss
                    source: "qrc:/image/cd2.jpg"
                    width: 50
                    height: 50

                    x:root.padding
                    y:(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.width
                              duration: 3000
                              running: root.running
                    }

                    // 旋转动画
                    RotationAnimation on rotation {
                              to:360
                              duration: 3000
                              running: root.running
                    }
                    // 颜色进行透明
                    PropertyAnimation on opacity {
                              to:0
                              duration: 3000
                              running: root.running
                    }
          }

          MouseArea{
                    anchors.fill: parent
                    onClicked: {
                              console.log("clicked...")
                              root.running = true
                    }
          }
}

注意:

此处是将动画放在控件里面,所有默认作用的对象是该控件;如果想放在控件之外,那么需要显示声明,目标对象,比如:

javascript 复制代码
Image{
    id:ss
    source: "qrc:/image/cd2.jpg"
    width: 50
    height: 50
}
PropertyAnimation on x{
    target: ss                  //指明作用对象
    to:root.width - ss.width
    duration: 3000
    running: root.running
}

//还可以这样写
PropertyAnimation{
    target:ss
    property:"x"                //指明属性
    to:root.width - ss.width
    duration:3000
    runing:root.running
}
  • 专门处理数值属性 - NumberAnimation

其实就是属性动画的特化版本

javascript 复制代码
NumberAnimation on x{
    target: ss
    to:root.width - ss.width
    duration: 3000
    running: root.running
}

// 其实等同于 
PropertyAnimation on x{
    target: ss                  //指明作用对象
    to:root.width - ss.width
    duration: 3000
    running: root.running
}
  • 专门处理颜色变化 - ColorAnimation

PropertyAnimation特化版

javascript 复制代码
ColorAnimation {
    target: colorRect
    property: "color"
    from: "red"
    to: "blue"
    duration: 2000
    loops: Animation.Infinite
    running: true
}

// 等同于
PropertyAnimation on color{
    target: colorRect                  //指明作用对象
    from: "red"
    to: "blue"
    duration: 2000
    loops: Animation.Infinite
    running: true
}

1.2、动画的触发方式

  • 主要存在以下几种方式触发:
    • 属性上的动画:在元素完全加载后自动运行
    • 属性上的行为:属性值更改时自动运行
    • 独立动画:使用start()显示启动动画或将running设置为true时运行
  • 属性上的动画:

在元素加载完成之后,立即自动运行,标志在于on

javascript 复制代码
PropertyAnimation on color{
    target: colorRect                  //指明作用对象
    from: "red"
    to: "blue"
    duration: 2000
    loops: Animation.Infinite
    running: true
}
  • 属性上的行为
    当属性值发生变化时自动触发动画,标志在于behavior
javascript 复制代码
// 行为动画:当x值改变时自动触发
Behavior on x {
    NumberAnimation {
        duration: 1000
    }
 }
  • 独立动画
    动画作为独立对象,需要通过代码进行显示启动
    • 调用start()
    • 设置runningtrue
javascript 复制代码
PropertyAnimation on color{
    id: color_anim
    target: colorRect                  //指明作用对象
    from: "red"
    to: "blue"
    duration: 2000
    //注意此处没有设置running为true,不会自动触发
}

Button {
    text: "running = true"
    onClicked: color_anim.running = true    //手动控制
}

小结:

触发方式 适用场景 优点 缺点
属性上的动画 页面加载动画、循环动画、不需要用户交互的动画 简单直接,自动运行 无法手动控制时机
属性上的行为 用户交互反馈、状态切换、属性绑定变化 自动响应属性变化 可能会在不希望的时机触发
独立动画 复杂动画序列,需要精确控制的动画 完全控制,可组合复杂动画 需要更多代码,手动进行管理

1.3、动画分组

  • 分组有两种方式:
    • 并行:将两组及以上动画同时执行
    • 顺序:先执行完一个动画后,再执行另一个动画
  • 并行动画
    关键词:ParallelAnimation
javascript 复制代码
ParallelAnimation{
    id:parallel_anim
    running: true
                    
    // 水平移动
    NumberAnimation{
        target: object
        property: "x"       //注意此时没使用on
        duration: 200
    }
                    
    // 旋转动画
    RotationAnimation{
        target: object
        property: "rotation"
        from: 0
        to: 360
        duration: 2000
    }
}
  • 顺序动画
    关键词SequentialAnimation
javascript 复制代码
SequentialAnimation{
    id:sequent_anim
    running: true
                    
    // 先水平移动
    NumberAnimation{
        target: object
        property: "x"       //注意此时没使用on
        duration: 200
    }
                    
    // 再旋转动画
    RotationAnimation{
        target: object
        property: "rotation"
        from: 0
        to: 360
        duration: 2000
    }
}

二、缓动曲线(Easing Curves)

2.1、什么是缓动曲线

描述了动画过程中属性值随时间变化的速率。它决定了动画是匀速运动、加速运动、减速运动还是有弹性的运动。

基本概念:

  • 线性(Linear): 匀速运动
  • 缓入(Easeln):开始慢,然后加速
  • 缓出(EaseOut): 开始快,然后减速
  • 缓入缓出(EaseInOut): 开始和结束都慢,中间快

2.2、缓动曲线类型

主要是通过easing.type属性来设置

javascript 复制代码
Behavior on scale{
    PropertyAnimation{
        duration:200
        easing.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、自定义贝塞尔曲线

如果需要更精确的控制,可以使用自定义贝塞尔曲线:

javascript 复制代码
PropertyAnimation {
    target: item
    property: "x"
    to: 300
    duration: 1000
    easing.type: Easing.Bezier
    easing.bezierCurve: [0.68, -0.55, 0.265, 1.55] // 自定义贝塞尔控制点
}

注意:

缓动曲线虽然带线,但只强调运动轨迹,运动的速率,而不是真的画线---视觉上的线条

三、小测

场景:画一个油量表,类似进度条,超过20%时,显示绿色,低于20%时显示红色报警

javascript 复制代码
import QtQuick

Item {
    id: oil_
    width:parent.width
    height: parent.height

    // 油量属性, 范围0-100
    property real fuelLevel: 75
    property color normalColor: "#00ff00"
    property color warnningColor: "#ff0000"
    property real warningValue: 20              // 警告阈值

    property int autoChangeDirection: -1        //自动改变方向

    Rectangle{
        id:background
        anchors.fill: parent
        color:"#2d2d2d"
        radius: 10
    }

    Column{
        anchors.fill: parent
        anchors.margins: 10
        spacing: 5

        Row{
            width:parent.width
            height: 20

            Text{
                text:"E"
                color:"white"
                font.pixelSize: 16
                font.bold: true
            }

            Item{
                width: parent.width - 40
                height: 1
            }

            Text{
                text:"F"
                color: "white"
                font.pixelSize: 16
                font.bold: true
            }
        }

        Rectangle{
            width: parent.width
            height: 25
            radius: 15

            // 进度条
            Rectangle{
                id:progressBar
                width: (fuelLevel / 100) * parent.width
                height: parent.height
                radius: parent.radius
                color:fuelLevel <= warningValue ? warnningColor : normalColor

                // 渐变效果
                gradient: Gradient{
                    GradientStop{
                        position: 0.0
                        color: Qt.lighter(progressBar.color, 1.2)
                    }

                    GradientStop{
                        position: 1.0
                        color: Qt.darker(progressBar.color, 1.2)
                    }
                }

                // 属性值动画
                Behavior on width{
                    NumberAnimation{
                        duration: 500
                        easing.type: Easing.OutCubic
                    }
                }
                // 颜色动画
                Behavior on color{
                    ColorAnimation {
                        duration: 300
                    }
                }
            }
            // 油量显示
            Text{
                id:fuelText
                anchors.horizontalCenter: parent.horizontalCenter
                text:fuelLevel.toFixed(1) + "%"
                color: fuelLevel <= warningValue ? warnningColor : normalColor
                font.pixelSize: 16
                font.bold: true

                Behavior on color{
                    ColorAnimation {
                        duration: 300
                    }
                }
            }
        }
    }
    Timer{
        id: autoChangeTimer
        interval: 200
        running: true
        repeat:true

        onTriggered: {
            //更新油量值
            fuelLevel += autoChangeDirection * 0.5

            if(fuelLevel >= 100){
                fuelLevel = 100
                autoChangeDirection = -1
            }else if (fuelLevel <= 0){
                fuelLevel = 0
                autoChangeDirection = 1
            }
        }
    }
}
相关推荐
太过平凡的小蚂蚁7 小时前
适配器模式:让不兼容的接口协同工作
java·前端·javascript
锈儿海老师7 小时前
超越平台:Vercel 的野心是定义编程语言的未来吗?
前端·javascript·架构
泷羽Sec-静安9 小时前
Less-7 GET-Dump into outfile-String
android·前端·网络·sql·安全·web安全
IT_陈寒9 小时前
从2秒到200ms:我是如何用JavaScript优化页面加载速度的🚀
前端·人工智能·后端
天天向上10249 小时前
vue 网站导航栏
前端·javascript·vue.js
云外天ノ☼9 小时前
一、Node.js入门实战指南:从零搭建你的第一个后端
前端·javascript·笔记·node.js
未来之窗软件服务10 小时前
未来之窗昭和仙君(四十八)开发商品进销存修仙版——东方仙盟筑基期
前端·仙盟创梦ide·东方仙盟·昭和仙君·东方仙盟架构
风清云淡_A10 小时前
【REACT16】react老项目版本依赖适配问题
前端·react.js
jump68010 小时前
【react】 useEffect
前端