admin管理员组

文章数量:1356736

I'm trying to create a scrolling posts animation in React using TailwindCSS and Framer Motion similar to this example link?

I tried to implement it this way, but it doesn’t work and doesn’t look as expected.

import { BsTwitterX, BsInstagram, BsThreads } from "react-icons/bs";
import "./App.css";
import { motion } from "framer-motion";

const posts = [
  {
    title: "#ultra25",
    username: "@user1",
    text: "Great vibes at Ultra Music Festival!",
    image: ".jpg",
    source: "instagram",
  },
  {
    title: "#ultra25",
    username: "@user2",
    text: "Epic night with amazing beats!",
    image: "",
    source: "twitter",
  },
  {
    title: "#ultra25",
    username: "@user3",
    text: "The best party of the year!",
    image: ".jpg",
    source: "threads",
  },
  {
    title: "#ultra25",
    username: "@user4",
    text: "Unfettable memories at Ultra!",
    image: "",
    source: "instagram",
  },
  {
    title: "#ultra25",
    username: "@user1",
    text: "Great vibes at Ultra Music Festival!",
    image: ".jpg",
    source: "instagram",
  },
  {
    title: "#ultra25",
    username: "@user2",
    text: "Epic night with amazing beats!",
    image: "",
    source: "twitter",
  },
  {
    title: "#ultra25",
    username: "@user3",
    text: "The best party of the year!",
    image:
      ";,
    source: "threads",
  },
  {
    title: "#ultra25",
    username: "@user4",
    text: "Unfettable memories at Ultra!",
    image: "",
    source: "instagram",
  },
  {
    title: "#ultra25",
    username: "@user1",
    text: "Great vibes at Ultra Music Festival!",
    image: ".jpg",
    source: "instagram",
  },
  {
    title: "#ultra25",
    username: "@user2",
    text: "Epic night with amazing beats!",
    image: "",
    source: "twitter",
  },
  {
    title: "#ultra25",
    username: "@user3",
    text: "The best party of the year!",
    image: ".jpg:large",
    source: "threads",
  },
  {
    title: "#ultra25",
    username: "@user4",
    text: "Unfettable memories at Ultra!",
    image: "",
    source: "instagram",
  },
  {
    title: "#ultra25",
    username: "@user1",
    text: "Great vibes at Ultra Music Festival!",
    image: ".jpg",
    source: "instagram",
  },
  {
    title: "#ultra25",
    username: "@user2",
    text: "Epic night with amazing beats!",
    image: "",
    source: "twitter",
  },
  {
    title: "#ultra25",
    username: "@user3",
    text: "The best party of the year!",
    image: ".jpg",
    source: "threads",
  },
  {
    title: "#ultra25",
    username: "@user4",
    text: "Unfettable memories at Ultra!",
    image: "",
    source: "instagram",
  },
];

const renderSocialIcon = (source: string) => {
  switch (source) {
    case "instagram":
      return <BsInstagram className="text-[#0077e7] w-[20px] h-[20px]" />;
    case "twitter":
      return <BsTwitterX className="text-[#0077e7] w-[20px] h-[20px]" />;
    case "threads":
      return <BsThreads className="text-[#0077e7] w-[20px] h-[20px]" />;
    default:
      return null;
  }
};

const App = () => {
  const createColumnAnimation = (colIndex) => ({
    animate: {
      y: ["0%", "-100%"],
      transition: {
        repeat: Infinity,
        repeatType: "loop",
        duration: 5,
        ease: "linear",
        delay: colIndex * 2,
      },
    },
  });

  return (
    <div className="min-h-screen bg-gray-100 pt-[180px] px-6">
      <div className="grid grid-cols-4 gap-6">
        {Array.from({ length: 4 }).map((_, colIndex) => (
          <motion.div
            key={colIndex}
            className="flex flex-col overflow-hidden relative"
            variants={createColumnAnimation(colIndex)}
            animate="animate"
          >
            <div className="flex flex-col">
              {posts
                .filter((_, index) => index % 4 === colIndex)
                .map((post, postIndex) => (
                  <div
                    key={postIndex}
                    className="bg-white rounded-lg shadow-lg flex flex-col min-h-[250px]"
                  >
                    <div className="flex justify-between items-center p-4">
                      <h3 className="text-xl font-bold text-black uppercase">
                        #ultra25
                      </h3>
                      <div className="flex space-x-4">
                        {renderSocialIcon(post.source)}
                      </div>
                    </div>
                    {post.image ? (
                      <img
                        src={post.image}
                        alt="Post"
                        style={{
                          height: "auto",
                          objectFit: "cover",
                          width: "100%",
                        }}
                      />
                    ) : null}
                    <div className="p-4">
                      <footer className="text-[#0084ff]">
                        <span className="font-semibold uppercase">
                          {post.username}
                        </span>
                        <p className="text-black">{post.text}</p>
                      </footer>
                    </div>
                  </div>
                ))}
            </div>
          </motion.div>
        ))}
      </div>
    </div>
  );
};

export default App;

What I’m trying to achieve:

  1. Each column scrolls upward by one post in 1 second.
  2. The next column starts scrolling 2 seconds after the previous one.
  3. The animation loops infinitely and smoothly.
  4. The effect should resemble continuous, seamless scrolling.

What’s not working:

  1. The animation doesn’t look smooth, and it feels jerky.
  2. It seems like the entire column scrolls rather than individual posts.
  3. It doesn’t create the smooth, infinite scrolling effect I’m aiming for.

Could the issue be related to using CSS Grid instead of Flexbox or maybe Is there a better way to handle this with Framer Motion?

Any help would be greatly appreciated!

Preview

本文标签: reactjsScrolling posts animation in React using TailwindCSS and Framer Motion like UltraStack Overflow