
目录Demo 1 缩放弹跳演示代码关键逻辑解析Demo 2 心跳脉冲演示代码关键逻辑解析Demo 3 弹性变形演示代码关键逻辑解析运行验证扩展复用方向有时候文字不需要入场而是需要持续地动起来提示用户注意或表达某种情绪。这篇介绍三种基于scale的形变动画缩放弹跳制造活泼的反馈感心跳脉冲模拟情感节奏弹性变形则像橡皮筋一样拉伸回弹。它们都只依赖Text的scale属性或Scale变换配合不同的缓动曲线就能做出丰富的效果。涉及的核心知识点SequentialAnimation on scale编排多段缩放Scale变换的非等比缩放xScale ≠ yScaleEasing.OutBack、Easing.InQuad、Easing.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 用OutBackInBack组合形成弹出去再拉回来的呼吸感第二个 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.25180ms快速缩回 1.0180ms再次放大到 1.15幅度稍小160ms再次缩回 1.0160ms然后停顿 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 } } } } }关键逻辑解析弹性变形的核心是让xScale和yScale成反方向变化横向拉长时纵向压扁横向压缩时纵向拉长并经过几次衰减震荡后回到 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让每次回弹在末尾减速看起来更自然。运行验证用 Qt Creator 打开qml_text/CMakeLists.txt按CtrlR运行项目在主界面找到缩放弹跳“心跳脉冲”弹性变形三个卡片观察循环效果。扩展复用方向把Demo_TextScaleBounce的循环动画改成由按钮点击触发做成点赞、收藏等交互反馈。把Demo_TextHeartbeat和按钮点击结合做成点赞/收藏的反馈动画。把Demo_TextElastic的弹性参数拉伸比、回弹次数、停顿时间暴露为接口做成按钮按下反馈。把心跳效果与消息通知结合收到新消息时心脏图标跳一下。已验证环境Qt 版本Qt 6.8.2、Qt 6.11.1操作系统Windows 11