目录
- Demo 1 重磅来袭
- 演示代码
- 关键逻辑解析
- Demo 2 路径动画
- 演示代码
- 关键逻辑解析
- Demo 3 文字抖动
- 演示代码
- 关键逻辑解析
- 运行验证
- 扩展复用方向
当文字需要被特别强调时,单纯的淡入淡出往往不够。重击入场用闪屏、冲击波和震动制造冲击力;路径动画把标题、下划线、描述按阶段编排入场;文字抖动则用高频随机位移营造紧张氛围。它们都适合用在标题、通知、错误提示等需要抓住用户眼球的地方。
涉及的核心知识点:
SequentialAnimation与ParallelAnimation编排复合动画- 闪屏矩形 + 冲击波圆环营造视觉爆发
Glow图形效果制作发光文字Timer高频触发随机位移和旋转
Demo 1 重磅来袭
这个 demo 模拟电影预告片里"重磅来袭"的冲击力:白色闪屏、红色冲击波、文字从 3.5 倍砸入,同时伴随高频震动。
以下演示代码来自
qml_text/Demo_TextHeavyStrike.qml,为便于阅读,只展示了关键代码。
演示代码
Rectangle { id: strikeCard width: 400; height: 200 color: "#0a0a0a" clip: true Rectangle { id: flash anchors.fill: parent color: "#FFFFFF" opacity: 0 z: 10 } Item { id: shakeContainer anchors.fill: parent Text { id: strikeText text: "重磅来袭" font.pointSize: 48 font.bold: true color: "#FF1744" anchors.centerIn: parent opacity: 0 style: Text.Outline styleColor: "#FFD600" } Rectangle { id: shockRing width: 0; height: width radius: width / 2 color: "transparent" border.color: "#FF1744" border.width: 3 anchors.centerIn: parent opacity: 0 z: -1 } } SequentialAnimation { loops: Animation.Infinite running: root.visible && root.opacity === 1 ScriptAction { script: { strikeText.scale = 3.5 strikeText.opacity = 0 flash.opacity = 0 shockRing.width = 0 shockRing.opacity = 0 shakeContainer.x = 0 } } ParallelAnimation { NumberAnimation { target: flash; property: "opacity"; from: 0; to: 0.9; duration: 100 } NumberAnimation { target: shockRing; property: "width"; from: 0; to: 500; duration: 500; easing.type: Easing.OutQuart } NumberAnimation { target: shockRing; property: "opacity"; from: 0.8; to: 0; duration: 500 } } ParallelAnimation { NumberAnimation { target: strikeText; property: "scale"; from: 3.5; to: 1.0; duration: 400; easing.type: Easing.OutBack } NumberAnimation { target: strikeText; property: "opacity"; from: 0; to: 1; duration: 200 } NumberAnimation { target: flash; property: "opacity"; from: 0.9; to: 0; duration: 300 } SequentialAnimation { NumberAnimation { target: shakeContainer; property: "x"; from: 0; to: -8; duration: 40 } NumberAnimation { target: shakeContainer; property: "x"; from: -8; to: 7; duration: 40 } NumberAnimation { target: shakeContainer; property: "x"; from: 7; to: -5; duration: 35 } NumberAnimation { target: shakeContainer; property: "x"; from: -5; to: 4; duration: 30 } NumberAnimation { target: shakeContainer; property: "x"; from: 4; to: -2; duration: 25 } NumberAnimation { target: shakeContainer; property: "x"; from: -2; to: 0; duration: 20 } } } PauseAnimation { duration: 1200 } ParallelAnimation { NumberAnimation { target: strikeText; property: "opacity"; from: 1; to: 0; duration: 300 } NumberAnimation { target: strikeText; property: "scale"; from: 1.0; to: 0.8; duration: 300 } } } }关键逻辑解析
重击动画分四层同时触发:闪屏矩形瞬间高亮再消失;冲击波圆环放大并淡出;文字从 3.5 倍缩小到正常大小并淡入;震动容器快速左右摆动后衰减。clip: true很重要,冲击波圆环会放大到超过卡片边界,不裁剪会溢出显示。四层动画时长不同,自然形成"闪屏 → 冲击波 → 文字砸入 → 震动"的节奏。
Demo 2 路径动画
这个 demo 展示页面标题组合入场:标题从左侧滑入并发光,下划线同步展开,描述文字随后淡入。
以下演示代码来自
qml_text/Demo_TextPathAnimation.qml,为便于阅读,只展示了关键代码。
演示代码
Rectangle { width: 400; height: 200 color: "#0d1117" clip: true Column { anchors.centerIn: parent spacing: 4 Text { id: slideTitle text: "Path Animation" font.pointSize: 28 font.bold: true color: "#64FFDA" x: -300 opacity: 0 layer.enabled: true layer.effect: Glow { color: "#64FFDA" radius: 8 spread: 0.2 transparentBorder: true } } Rectangle { id: underline width: 0 height: 3 radius: 1.5 gradient: Gradient { orientation: Gradient.Horizontal GradientStop { position: 0.0; color: "#64FFDA" } GradientStop { position: 0.5; color: "#58A6FF" } GradientStop { position: 1.0; color: "#64FFDA" } } } Text { id: slideDesc text: "标题滑入 + 下划线展开 + 文字淡入" font.pointSize: 11 color: "#8B949E" opacity: 0 anchors.horizontalCenter: parent.horizontalCenter } } SequentialAnimation { id: entryAnim PropertyAction { target: slideTitle; property: "x"; value: -300 } PropertyAction { target: slideTitle; property: "opacity"; value: 0 } PropertyAction { target: underline; property: "width"; value: 0 } PropertyAction { target: slideDesc; property: "opacity"; value: 0 } ParallelAnimation { NumberAnimation { target: slideTitle; property: "x"; to: 0; duration: 600; easing.type: Easing.OutBack } NumberAnimation { target: slideTitle; property: "opacity"; to: 1; duration: 400 } } NumberAnimation { target: underline; property: "width"; to: slideTitle.width; duration: 500; easing.type: Easing.OutCubic } NumberAnimation { target: slideDesc; property: "opacity"; to: 1; duration: 400 } } Component.onCompleted: entryAnim.start() }关键逻辑解析
三个阶段依次发生:标题滑入并带Glow发光;下划线宽度从 0 展开到标题宽度;描述文字淡入。PropertyAction在动画开始时重置状态,保证每次进入页面都能看到完整入场。标题使用Qt5Compat.GraphicalEffects的Glow效果,spread: 0.2和radius: 8让文字有一层青色外发光。
Demo 3 文字抖动
这个 demo 用Timer每 60ms 随机改变文字的 x、y 偏移和旋转角度,制造紧张、警告的感觉。
以下演示代码来自
qml_text/Demo_TextShake.qml,为便于阅读,只展示了关键代码。
演示代码
// 控制抖动阶段与停顿阶段交替 property bool shakeActive: false Text { id: shakeText text: "⚠ 警告!文字抖动" font.pointSize: 24 font.bold: true color: "#D32F2F" anchors.centerIn: parent transform: [ Translate { id: shakeTranslate }, Rotation { id: shakeRotation origin.x: shakeText.width / 2 origin.y: shakeText.height / 2 } ] } Timer { interval: 60 running: root.shakeActive && root.visible && root.opacity === 1 repeat: true onTriggered: { shakeTranslate.x = Math.random() * 10 - 5 shakeTranslate.y = Math.random() * 8 - 4 shakeRotation.angle = Math.random() * 8 - 4 } } // 抖动 1.5s,停顿 1.2s,循环播放 SequentialAnimation { running: root.visible && root.opacity === 1 loops: Animation.Infinite ScriptAction { script: root.shakeActive = true } PauseAnimation { duration: 1500 } ScriptAction { script: { root.shakeActive = false shakeTranslate.x = 0 shakeTranslate.y = 0 shakeRotation.angle = 0 } } PauseAnimation { duration: 1200 } }关键逻辑解析
Text用anchors.centerIn做居中定位,Translate和Rotation在此基础上叠加偏移和旋转,不会破坏初始布局。Math.random() * 10 - 5生成 -5 到 5 像素的水平偏移,旋转范围设为 -4° 到 4°。interval: 60接近 17fps,足够制造抖动感又不会太耗性能。
为了避免一直抖动造成视觉疲劳,这里增加了一个shakeActive状态,并用SequentialAnimation控制抖动阶段和停顿阶段交替:抖动 1.5s 后关闭shakeActive,并把位移/旋转归零,停顿 1.2s 后再开启下一轮抖动。把Timer.running绑定到root.shakeActive,就能实现“抖—停—抖”的节奏。
运行验证
- 用 Qt Creator 打开
qml_text/CMakeLists.txt; - 按
Ctrl+R运行项目; - 在主界面找到"重磅来袭"“路径动画”"文字抖动"三个卡片,观察循环效果。
扩展复用方向
- 把重击动画封装成
ImpactText组件,暴露text、flashColor、shockColor等属性。 - 把路径动画提取成页面标题组件,支持标题、描述、下划线颜色自定义。
- 把抖动封装成
ShakeText,支持触发一次或持续抖动两种模式。
已验证环境:
- Qt 版本:Qt 6.8.2、Qt 6.11.1
- 操作系统:Windows 11