使文字适合剩余空间并保持相同的运动效果

问题描述 投票:0回答:1

我有一个具有以下结构的 Next js 项目:

.
├── media
│   └── img.jpg
├── package.json
├── package-lock.json
├── postcss.config.js
├── src
│   ├── components
│   │   └── AnimatedCharacters.js
│   ├── pages
│   │   ├── _app.js
│   │   ├── index.js
│   │   └── index_.js
│   └── styles
│       └── global.css
└── tailwind.config.js

文件内容如下:
包.json

{
  "private": true,
  "scripts": {
    "build": "next build",
    "dev": "next dev",
    "start": "next start"
  },
  "dependencies": {
    "eslint": "^8.54.0",
    "framer-motion": "^10.16.5",
    "next": "latest",
    "react": "18.2.0",
    "react-dom": "18.2.0"
  },
  "engines": {
    "node": ">=18"
  },
  "devDependencies": {
    "autoprefixer": "^10.4.16",
    "postcss": "^8.4.31",
    "tailwindcss": "^3.3.5"
  }
}

postcss.config.js

module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
}

tailwind.config.js

/** @type {import('tailwindcss').Config} */

const { fontfamily } = require("tailwindcss/defaultTheme");

module.exports = {
  content: ["./src/**/*.{js,ts,jsx,tsx,mdx}"],
  theme: {
    extend: {
      fontFamily: {
        poppins: ["var(--font-poppins)"],
      },
      colors: {
        dark: "#1b1b1b",
        light: "#f5f5f5",
        primary: "#B63E96", // 240,86,199
        primaryDark: "#58E6D9", // 80,230,217
        white: "#fff",
        light_purple: "#8490ff",
        light_white: "#f9f9ff",
        text_color: "#777777",
      },
    },
    borderWidth: {
      1: "1px",
      2: "2px",
    },
  },
  plugins: [],
};

src/styles/global.css

@tailwind base;
@tailwind components;
@tailwind utilities;

src/pages/_app.js

import Head from "next/head";
import "../styles/global.css";
import { Poppins } from "next/font/google";

const poppins = Poppins({
  subsets: ["latin"],
  variable: "--font-poppins",
  weight: ["100", "200", "400", "300", "500", "600", "700"],
});

export default function App({ Component, pageProps }) {
  return (
    <>
      <Head>
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <main className={`${poppins.variable} font-poppins`}>
        <Component {...pageProps} />
      </main>
    </>
  );
}

src/pages/index.js

import Head from "next/head";
import Image from "next/image";
import profilepicture from "../../media/img.jpg";

export default function Home() {
  return (
    <div>
      <Head>
        <title>Create Next App</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <main className="w-full h-auto pl-14 pr-14 flex bg-light_white text-black">
        <div className="flex items-center justify-between w-full pt-20 pb-20">
          <div className="flex-1 pr-14">
            <p className="text-text_color mb-2">
              Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
              eiusmod tempor incididunt ut labore et dolore magna aliqua.
            </p>
            <p className="text-text_color mb-2">
              Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
              eiusmod tempor incididunt ut labore et dolore magna aliqua.
            </p>
            <p className="text-text_color mb-2">
              Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
              eiusmod tempor incididunt ut labore et dolore magna aliqua.
            </p>
          </div>
          <div className="w-80 h-80">
            <Image
              src={profilepicture}
              alt="bird"
              className="w-full h-full object-cover rounded-full"
            />
          </div>
        </div>
      </main>
    </div>
  );
}

运行时

npm run dev
,这按预期工作;文本占据图像放置好后留下的空间。

此外,当我调整窗口大小时,文本也会适应空间。

但是,当我添加

AnimatedCharacters.js
组件时,文本会占用尽可能多的空间,当我调整大小时,文本甚至超过了屏幕的宽度。

这里是代码:
src/components/AnimatedCharacters.js

import React from "react";
import { motion } from "framer-motion";

export default function AnimatedCharacters({
  text,
  className = "",
  reverse = false,
}) {
  // splitting text into letters
  const letters = Array.from(text);

  // Variants for Container
  const container = {
    hidden: { opacity: 0 },
    visible: (i = 1) => ({
      opacity: 1,
      transition: {
        staggerChildren: 0.02,
        delayChildren: 0.03 * i,
        staggerDirection: reverse ? -1 : 1, // Adjust staggerDirection based on reverse prop
      },
    }),
  };

  // Variants for each letter
  const child = {
    visible: {
      opacity: 1,
      x: 0,
      y: 0,
      transition: {
        type: "spring",
        damping: 12,
        stiffness: 100,
      },
    },
    hidden: {
      opacity: 0,
      x: reverse ? 20 : -20, // Adjust initial x position based on reverse prop
      y: 10,
      transition: {
        type: "spring",
        damping: 12,
        stiffness: 100,
      },
    },
  };

  return (
    <motion.div
      className={className}
      variants={container}
      initial="hidden"
      animate="visible"
    >
      {letters.map((letter, index) => (
        <motion.span variants={child} key={index}>
          {letter === " " ? "\u00A0" : letter}
        </motion.span>
      ))}
    </motion.div>
  );
}

这就是添加新组件后 index.js 的样子:

import Head from "next/head";
import Image from "next/image";
import profilepicture from "../../media/img.jpg";
import AnimatedCharacters from "../components/AnimatedCharacters";

export default function Home() {
  return (
    <div>
      <Head>
        <title>Create Next App</title>
      </Head>
      <main className="w-full h-auto pl-14 pr-14 flex bg-light_white text-black">
        <div className="flex items-center justify-between w-full pt-20 pb-20">
          <div className="pr-14">
            <AnimatedCharacters
              text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed
              do eiusmod tempor incididunt ut labore et dolore magna aliqua."
              className="text-text_color mb-2 overflow-hidden flex"
            />
            <AnimatedCharacters
              text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed
              do eiusmod tempor incididunt ut labore et dolore magna aliqua."
              reverse
              className="text-text_color mb-2 overflow-hidden flex"
            />
            <AnimatedCharacters
              text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed
              do eiusmod tempor incididunt ut labore et dolore magna aliqua."
              className="text-text_color mb-2 overflow-hidden flex"
            />
          </div>
          <div className="w-80 h-80">
            <Image
              src={profilepicture}
              alt="bird"
              className="w-full h-full object-cover rounded-full"
            />
          </div>
        </div>
      </main>
    </div>
  );
}

这是我刚刚制作的视频记录的链接。

有没有办法让文本适合放置图像后剩下的空间,并将运动效果逐行应用于格式化文本(即从左侧出现第 n 行,从右侧出现第 n+1 行)?

我正在使用 Tailwind CSS 和 framer-motion

reactjs next.js tailwind-css framer-motion
1个回答
0
投票

如果你设法让文本在 div 内换行

这行有问题

{letter === " " ? "\u00A0" : letter}
因为现在每个字母都在 span 中,所以让我们说单词 text 如果您调整页面大小,它可能不会显示text,它可能是这样的:


xt

所以在将文本拆分为字母之前

const letters = Array.from(text);

你必须将跨度中的每个单词分开

代码:

const text="separate- every- word- with- any- symbol- also- with- a- white- space"

return (
       <div>
      {text
        .replaceAll("-", `${"\u00A0"}`)
        .split(" ")
        .map((word, i) => (
          <div key={"word" + i}>
            {word.split("").map((letter, i) => (
              <motion.span key={"letter" + i}>{letter}</motion.span>
            ))}
          </div>
        ))}
    </div>
)

你必须用符号分隔

const text
中的每个单词,这样你就可以用它来替换每个单词之间的空格

  1. 我所做的是
    text
    我用空格替换了符号
    ${"\u00A0"}
  2. 我使用了 split ,值是空格
    " "
    来分隔每个单词
  3. 我再次使用 split 将每个单词中的每个字母分开并放入
    motion.span
© www.soinside.com 2019 - 2024. All rights reserved.