You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 22:36:19