QML 文字弹跳与形变动画:缩放弹跳、心跳、弹性
2026/7/22 13:57:08 网站建设 项目流程

目录

    • Demo 1 缩放弹跳
      • 演示代码
      • 关键逻辑解析
    • Demo 2 心跳脉冲
      • 演示代码
      • 关键逻辑解析
    • Demo 3 弹性变形
      • 演示代码
      • 关键逻辑解析
    • 运行验证
    • 扩展复用方向

有时候文字不需要入场,而是需要持续地"动"起来,提示用户注意或表达某种情绪。这篇介绍三种基于scale的形变动画:缩放弹跳制造活泼的反馈感,心跳脉冲模拟情感节奏,弹性变形则像橡皮筋一样拉伸回弹。它们都只依赖Textscale属性或Scale变换,配合不同的缓动曲线就能做出丰富的效果。

涉及的核心知识点:

  • SequentialAnimation on scale编排多段缩放
  • Scale变换的非等比缩放(xScale ≠ yScale)
  • Easing.OutBackEasing.InQuadEasing.OutQuad等缓动曲线
  • 用多段动画组合模拟真实物理节奏

Demo 1 缩放弹跳

这个 demo 展示了如何用scale属性做出持续性的弹性反馈。两个 Text 分别用不同的关键帧组合:一个从正常大小放大再缩回,另一个做"大 → 小 → 正常"的弹跳。

以下演示代码来自qml_text/Demo_TextScaleBounce.qml,为便于阅读,只展示了关键代码。

演示代码

import QtQuick import QtQuick.Layouts DemoPage { id: root title: "缩放弹跳" description: "scale 属性配合 OutBack / InBack 缓动,让文字产生弹性缩放。" ColumnLayout { Layout.fillWidth: true Layout.alignment: Qt.AlignHCenter spacing: 30 Text { text: "缩放弹跳动画" font.pointSize: 22 font.bold: true color: "#9C27B0" Layout.alignment: Qt.AlignHCenter SequentialAnimation on scale { loops: Animation.Infinite running: root.visible && root.opacity === 1 NumberAnimation { from: 1.0; to: 1.35; duration: 500; easing.type: Easing.OutBack } NumberAnimation { from: 1.35; to: 1.0; duration: 500; easing.type: Easing.InBack } } } Text { text: "Bounce!" font.pointSize: 22 font.bold: true color: "#4CAF50" Layout.alignment: Qt.AlignHCenter SequentialAnimation on scale { loops: Animation.Infinite running: root.visible && root.opacity === 1 NumberAnimation { from: 1.0; to: 1.2; duration: 300; easing.type: Easing.OutBack } NumberAnimation { from: 1.2; to: 0.9; duration: 200; easing.type: Easing.InQuad } NumberAnimation { from: 0.9; to: 1.0; duration: 200; easing.type: Easing.OutBack } PauseAnimation { duration: 800 } } } } }

关键逻辑解析

scale的默认变换原点是元素中心,所以放大缩小时文字会保持居中,不需要额外计算坐标。第一个 Text 用OutBack+InBack组合,形成"弹出去再拉回来"的呼吸感;第二个 Text 多加了一个0.9的中间状态,配合OutBack回弹,更像按钮被按下后弹起的效果。

这种持续缩放很适合做提示性动画,比如"新消息"角标、未读提醒、限时活动标签等。只需要把loops: Animation.Infinite改成只播放一次,或者把触发条件绑定到某个状态变化上,就能从"循环提示"切换成"交互反馈"。


Demo 2 心跳脉冲

这个 demo 模拟心跳节奏:文字快速缩放两次(“怦-怦”),然后停顿一秒多,再重复。适合用于爱心、点赞、收藏等需要表达情感的场景。

以下演示代码来自qml_text/Demo_TextHeartbeat.qml,为便于阅读,只展示了关键代码。

演示代码

import QtQuick import QtQuick.Layouts DemoPage { id: root title: "心跳脉冲" description: "模拟心跳的两段急促缩放 + 停顿,适合用于强调、点赞、爱心等场景。" Rectangle { Layout.fillWidth: true Layout.preferredHeight: 160 color: "#FFEBEE" radius: 8 Text { text: "♥ 心跳" font.pointSize: 32 font.bold: true color: "#E91E63" anchors.centerIn: parent SequentialAnimation on scale { loops: Animation.Infinite running: root.visible && root.opacity === 1 NumberAnimation { from: 1.0; to: 1.25; duration: 180; easing.type: Easing.OutQuad } NumberAnimation { from: 1.25; to: 1.0; duration: 180; easing.type: Easing.InQuad } NumberAnimation { from: 1.0; to: 1.15; duration: 160; easing.type: Easing.OutQuad } NumberAnimation { from: 1.15; to: 1.0; duration: 160; easing.type: Easing.InQuad } PauseAnimation { duration: 1200 } } } } }

关键逻辑解析

心跳动画由四个NumberAnimation组成:

  1. 快速放大到 1.25(180ms)
  2. 快速缩回 1.0(180ms)
  3. 再次放大到 1.15,幅度稍小(160ms)
  4. 再次缩回 1.0(160ms)

然后停顿 1.2 秒,模拟两次心跳之间的舒张期。第一次缩放幅度大,第二次幅度小,非常接近真实心跳的"怦-怦"节奏。scale的变换原点在文字中心,所以缩放时不会偏移。如果想让心跳更生动,可以在放大时同时加深颜色或加一层发光;如果想做成点赞反馈,可以把loops: Animation.Infinite去掉,只在点击时播放一次。


Demo 3 弹性变形

这个效果让文字像橡皮筋一样被横向拉伸、纵向压缩,然后回弹,反复几次后恢复原始比例。适合用作强调、提示或按钮按下后的反馈。

以下演示代码来自qml_text/Demo_TextElastic.qml,为便于阅读,只展示了关键代码。

演示代码

import QtQuick import QtQuick.Layouts DemoPage { id: root title: "弹性变形" description: "文字像橡皮筋一样横向拉伸纵向压缩,Q 弹回弹。" Rectangle { Layout.fillWidth: true Layout.preferredHeight: 160 Layout.alignment: Qt.AlignHCenter color: "#1a1a2e" radius: 12 Text { id: elasticText text: "弹性变形" font.pointSize: 48 font.bold: true color: "#FF6B35" anchors.centerIn: parent transform: Scale { id: elasticScale origin.x: elasticText.width / 2 origin.y: elasticText.height / 2 xScale: 1.0 yScale: 1.0 } SequentialAnimation { running: root.visible && root.opacity === 1 loops: Animation.Infinite // 横向拉伸、纵向压缩 ParallelAnimation { NumberAnimation { target: elasticScale; property: "xScale"; from: 1.0; to: 1.6; duration: 200; easing.type: Easing.OutQuad } NumberAnimation { target: elasticScale; property: "yScale"; from: 1.0; to: 0.6; duration: 200; easing.type: Easing.OutQuad } } // 弹回:横向压缩、纵向拉伸 ParallelAnimation { NumberAnimation { target: elasticScale; property: "xScale"; from: 1.6; to: 0.7; duration: 150; easing.type: Easing.OutQuad } NumberAnimation { target: elasticScale; property: "yScale"; from: 0.6; to: 1.3; duration: 150; easing.type: Easing.OutQuad } } // 回弹 ParallelAnimation { NumberAnimation { target: elasticScale; property: "xScale"; from: 0.7; to: 1.2; duration: 200; easing.type: Easing.OutQuad } NumberAnimation { target: elasticScale; property: "yScale"; from: 1.3; to: 0.9; duration: 200; easing.type: Easing.OutQuad } } ParallelAnimation { NumberAnimation { target: elasticScale; property: "xScale"; from: 1.2; to: 0.95; duration: 150; easing.type: Easing.OutQuad } NumberAnimation { target: elasticScale; property: "yScale"; from: 0.9; to: 1.05; duration: 150; easing.type: Easing.OutQuad } } // 归位 ParallelAnimation { NumberAnimation { target: elasticScale; property: "xScale"; from: 0.95; to: 1.0; duration: 100; easing.type: Easing.OutQuad } NumberAnimation { target: elasticScale; property: "yScale"; from: 1.05; to: 1.0; duration: 100; easing.type: Easing.OutQuad } } PauseAnimation { duration: 1000 } } } } }

关键逻辑解析

弹性变形的核心是让xScaleyScale成反方向变化:横向拉长时纵向压扁,横向压缩时纵向拉长,并经过几次衰减震荡后回到 1:1。Scale变换的origin设在文字中心,这样变形时文字不会偏移位置。

五个ParallelAnimation阶段分别是:拉扁(x 1.6, y 0.6)、反向回弹(x 0.7, y 1.3)、二次震荡(x 1.2, y 0.9)、三次震荡(x 0.95, y 1.05)、归位(x 1.0, y 1.0)。每次变化的幅度越来越小,模拟真实橡皮筋的能量衰减。Easing.OutQuad让每次回弹在末尾减速,看起来更自然。


运行验证

  1. 用 Qt Creator 打开qml_text/CMakeLists.txt
  2. Ctrl+R运行项目;
  3. 在主界面找到"缩放弹跳"“心跳脉冲”"弹性变形"三个卡片,观察循环效果。

扩展复用方向

  • Demo_TextScaleBounce的循环动画改成由按钮点击触发,做成点赞、收藏等交互反馈。
  • Demo_TextHeartbeat和按钮点击结合,做成点赞/收藏的反馈动画。
  • Demo_TextElastic的弹性参数(拉伸比、回弹次数、停顿时间)暴露为接口,做成按钮按下反馈。
  • 把心跳效果与消息通知结合:收到新消息时心脏图标跳一下。

已验证环境:

  • Qt 版本:Qt 6.8.2、Qt 6.11.1
  • 操作系统:Windows 11

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询