如何使用Framer Motion实现数组文本循环切换波浪文字动画
数组轮播波浪文字动画实现方案
核心要补的是动画时序控制和文本切换逻辑,原有单条文本的波浪动画渲染逻辑基本可以复用,不用全量重构。
核心逻辑拆解
- 文本统一存在预设数组里,不硬编码单条内容
- 单条文本的入场波浪动画完全播放结束后,自动触发退场隐藏动效
- 退场动效播放完成后,自动切换到数组下一条文本,循环触发入场波浪动画
- 数组遍历到末尾后自动回到第一条,实现无限轮播
具体实现步骤
1. 声明基础状态与常量
先在组件里定义文本源、控制状态,以及动画时长相关的可调参数:
import { useState, useEffect } from 'react' import './animated-text.css' // 波浪动画文本数组,可自行替换内容 const TEXT_LIST = [ "Hello World", "Wavy Text Animation", "Loop Play Text Effect" ] // 动画参数,可根据想要的效果调整 const CHAR_ANIM_DELAY = 45 // 单个字符启动动画的间隔延迟,值越小波浪滚动越快 const CHAR_ANIM_DURATION = 900 // 单个字符波浪动画的总时长 const LEAVE_ANIM_DURATION = 280 // 文本退场隐藏动画的时长 export default function AnimatedText() { // 当前显示的文本索引 const [currentIdx, setCurrentIdx] = useState(0) // 标记当前是否处于退场阶段 const [isLeaving, setIsLeaving] = useState(false) // 后续补时序控制逻辑 }
2. 加动画时序控制逻辑
计算单条文本入场动画的总时长,等动画走完自动触发退场,退场完成后切换文本索引重置状态:
useEffect(() => { const currentText = TEXT_LIST[currentIdx] // 入场动画总时长 = 最后一个字符的启动延迟 + 单字符动画时长 const enterTotalTime = currentText.length * CHAR_ANIM_DELAY + CHAR_ANIM_DURATION const enterTimer = setTimeout(() => { // 入场播完,启动退场 setIsLeaving(true) const leaveTimer = setTimeout(() => { // 退场播完,切下一条,到数组末尾就回到第一条 setCurrentIdx(prev => (prev + 1) % TEXT_LIST.length) setIsLeaving(false) }, LEAVE_ANIM_DURATION) return () => clearTimeout(leaveTimer) }, enterTotalTime) return () => clearTimeout(enterTimer) }, [currentIdx])
3. 调整渲染逻辑
把原来硬编码的文本替换成当前索引对应的文本,按字符拆分后逐个加波浪动画样式,退场阶段给容器加对应的状态类:
return ( <div className={`wavy-text-container ${isLeaving ? 'is-leaving' : ''}`}> {TEXT_LIST[currentIdx].split('').map((char, idx) => ( <span key={`${currentIdx}-${idx}`} className="wavy-char" style={{ animationDelay: `${idx * CHAR_ANIM_DELAY}ms`, animationDuration: `${CHAR_ANIM_DURATION}ms` }} > {/* 空格转不换行空格,避免渲染时空格被合并导致错位 */} {char === ' ' ? '\u00A0' : char} </span> ))} </div> )
4. 补对应样式
退场阶段覆盖原有入场动画,换成隐藏动效即可:
.wavy-text-container { font-size: 48px; font-weight: 600; } .wavy-char { display: inline-block; animation: wavyEnter ease forwards; } /* 退场状态下所有字符统一执行淡出动画 */ .wavy-text-container.is-leaving .wavy-char { animation: wavyLeave ease forwards !important; animation-duration: 280ms !important; animation-delay: 0ms !important; } @keyframes wavyEnter { 0% { transform: translateY(24px); opacity: 0; } 40% { transform: translateY(-8px); } 100% { transform: translateY(0); opacity: 1; } } @keyframes wavyLeave { to { transform: translateY(-16px); opacity: 0; } }
优化提示
- 如果想要更丝滑的衔接效果,可以不用等退场完全结束再切文本,把新文本提前渲染在下层,退场动画启动的同时新文本就开始播放入场动画,只要调整定时器触发时机即可
- 记得在useEffect里清理定时器,避免组件卸载后内存泄漏,或者索引更新后重复触发动画
- 字符key带上当前索引值,避免切换文本时React复用DOM节点导致动画不触发
内容的提问来源于stack exchange,提问作者Hasan Mobarak
相关产品推荐
相关产品推荐

