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

Next.js中实现文本适配剩余空间并保留逐行动画效果的问询

解决方案

1. 修复文本溢出的布局问题

用Tailwind的flex布局锁定文本容器的可用空间,避免溢出:

  • 外层用flex容器,图片设置自适应宽度,文本容器添加flex-1 overflow-hidden,确保只占用图片旁的剩余空间,同时限制内容溢出。
  • 示例结构:
<div className="flex flex-col md:flex-row gap-4">
  <img src="/your-image.jpg" alt="示例图" className="w-full md:w-1/3 object-cover" />
  <div className="flex-1 overflow-hidden">
    <AnimatedText text={yourContent} />
  </div>
</div>

这里flex-1让文本容器填充剩余空间,overflow-hidden配合默认的whitespace-normal实现文本自动换行适配。

2. 实现逐行交替方向的framer-motion动画

步骤1:拆分文本为独立行

通过临时元素计算每行可容纳的内容,确保拆分结果和实际显示一致:

步骤2:编写AnimatedText组件

import { motion } from 'framer-motion';
import { useEffect, useState } from 'react';

const AnimatedText = ({ text }) => {
  const [lines, setLines] = useState([]);

  useEffect(() => {
    const container = document.getElementById('text-wrapper');
    if (!container) return;

    const words = text.split(' ');
    const currentLine = [];
    const lineList = [];
    
    // 创建临时元素计算行高
    const tempEl = document.createElement('div');
    tempEl.className = 'whitespace-normal';
    tempEl.style.visibility = 'hidden';
    tempEl.style.position = 'absolute';
    container.appendChild(tempEl);

    words.forEach(word => {
      currentLine.push(word);
      tempEl.textContent = currentLine.join(' ');
      // 当临时元素高度超过容器单行列高时,拆分当前行
      if (tempEl.offsetHeight > container.offsetHeight / (lineList.length + 1)) {
        currentLine.pop();
        lineList.push(currentLine.join(' '));
        currentLine.push(word);
      }
    });
    currentLine.length > 0 && lineList.push(currentLine.join(' '));

    container.removeChild(tempEl);
    setLines(lineList);
  }, [text]);

  // 监听窗口 resize,重新计算行
  useEffect(() => {
    const recalculateLines = () => {
      const container = document.getElementById('text-wrapper');
      if (!container) return;

      const words = text.split(' ');
      const currentLine = [];
      const lineList = [];
      
      const tempEl = document.createElement('div');
      tempEl.className = 'whitespace-normal';
      tempEl.style.visibility = 'hidden';
      tempEl.style.position = 'absolute';
      container.appendChild(tempEl);

      words.forEach(word => {
        currentLine.push(word);
        tempEl.textContent = currentLine.join(' ');
        if (tempEl.offsetHeight > container.offsetHeight / (lineList.length + 1)) {
          currentLine.pop();
          lineList.push(currentLine.join(' '));
          currentLine.push(word);
        }
      });
      currentLine.length > 0 && lineList.push(currentLine.join(' '));

      container.removeChild(tempEl);
      setLines(lineList);
    };

    window.addEventListener('resize', recalculateLines);
    return () => window.removeEventListener('resize', recalculateLines);
  }, [text]);

  return (
    <div id="text-wrapper" className="whitespace-normal">
      {lines.map((line, index) => (
        <motion.div
          key={index}
          initial={{ 
            x: index % 2 === 0 ? -100 : 100,
            opacity: 0
          }}
          animate={{ 
            x: 0,
            opacity: 1
          }}
          transition={{ duration: 0.6, delay: index * 0.2 }}
          className="mb-1"
        >
          {line}
        </motion.div>
      ))}
    </div>
  );
};

export default AnimatedText;

关键说明

  • 动画逻辑:偶数行(索引从0开始)从左侧(x: -100)滑入,奇数行从右侧(x: 100)滑入,配合透明度渐变,逐行添加延迟让动画更有层次感。
  • 响应式适配:监听窗口 resize 事件,重新计算每行内容,保证窗口缩放时动画行和实际显示行一致。

内容的提问来源于stack exchange,提问作者singrium

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 18:23:28