使用ReactJS和CSS连续循环动画滚动

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

我必须使用 React 和 CSS 创建一个连续循环的动画滚动。目标是创建自动滚动并连续循环列表,因此在列表的最后一个元素之后我应该有第一个元素等等,这就是我目前所拥有的:

我现在遇到的问题是,当最后一个元素滚动时,我得到一个空白页面,应该等待 3 或 4 秒,然后一次又一次循环,并且我想在第 5 项之后获取第 1 项,依此类推。不确定它是否是清楚,这是我目前的代码:

import { useRef, useEffect, useState } from "react";
import Card from "./Card.js";

import "./styles.css";

let data = [
  {
    Name: "1"
  },
  {
    Name: "2"
  },

  {
    Name: "3"
  },

  {
    Name: "4"
  },

  {
    Name: "5"
  }
];

export default function App() {
  const ref = useRef(null);
  const [containerWidth, setWidth] = useState(100 + "%");
  const [animationState, setPlay] = useState("paused");
  useEffect(() => {
    if (ref.current) {
      setWidth(ref.current.scrollWidth + "px");
      setPlay("running");
    }
  }, []);
  console.log(containerWidth);
  const renderCards = data.map((el, index) => {
    return <Card key={index} cardName={el.Name} />;
  });

  return (
    <div className="App">
      <div
        className="d-flex"
        ref={ref}
        style={{
          width: `${containerWidth}`,
          animationPlayState: animationState
        }}
      >
        {renderCards}
      </div>
    </div>
  );
}
.App {
  overflow: hidden;
}
.card {
  width: 200px !important;
  height: 200px;
  background: #ffefef;
  box-shadow: 0px 1px 4px 1px rgba(158, 151, 151, 0.25);
  border-radius: 15px;
  margin: 12px;
  padding: 12px;
}
.d-flex {
  transform: translateY(calc(100vw));
  overflow: visible;
  animation: animateContainer 5s linear forwards infinite;
}
@keyframes animateContainer {
  from {
    transform: translateY(calc(100vw));
  }
  to {
    transform: translateY(calc(-100%));
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

这是我的沙箱项目

reactjs scroll css-animations infinite-scroll
1个回答
0
投票

保留第一个列表下的项目列表的副本。当副本到达顶部时重置动画。对于大多数意图和目的来说,这将使它看起来无穷无尽。在

translateY(0)
(列表顶部位于顶部)和
translateY(-50%)
(列表副本顶部位于顶部)之间进行动画处理:

const { useRef, useEffect, useState } = React;

function Card({ cardName, refCard }) {
  return (
    <div className="bubble" ref={refCard}>
      <div className="card m-2 pt-2">
        <div className="py-1">
          <div className="fs-5 mt-2">{cardName}</div>
        </div>
      </div>
    </div>
  );
}

let data = [
  {
    Name: "1"
  },
  {
    Name: "2"
  },

  {
    Name: "3"
  },

  {
    Name: "4"
  },

  {
    Name: "5"
  }
];

function App() {
  const ref = useRef(null);
  const [containerWidth, setWidth] = useState(100 + "%");
  const [animationState, setPlay] = useState("paused");
  useEffect(() => {
    if (ref.current) {
      setWidth(ref.current.scrollWidth + "px");
      setPlay("running");
    }
  }, []);
  console.log(containerWidth);
  const renderCards = data.map((el, index) => {
    return <Card key={index} cardName={el.Name} />;
  });

  return (
    <div className="App">
      <div
        className="d-flex"
        ref={ref}
        style={{
          width: `${containerWidth}`,
          animationPlayState: animationState
        }}
      >
        {renderCards}
        {renderCards}
      </div>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('app')).render(<App/>);
.App {
  overflow: hidden;
}
.card {
  width: 200px !important;
  height: 200px;
  background: #ffefef;
  box-shadow: 0px 1px 4px 1px rgba(158, 151, 151, 0.25);
  border-radius: 15px;
  margin: 12px;
  padding: 12px;
}
.d-flex {
  overflow: visible;
  animation: animateContainer 5s linear forwards infinite;
}
@keyframes animateContainer {
  from {
    transform: translateY(0);
  }
  to {
    transform: translateY(-50%);
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js" integrity="sha512-8Q6Y9XnTbOE+JNvjBQwJ2H8S+UV4uA6hiRykhdtIyDYZ2TprdNmWOUaKdGzOhyr4dCyk287OejbPvwl7lrfqrQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js" integrity="sha512-MOCpqoRoisCTwJ8vQQiciZv0qcpROCidek3GTFS6KTk2+y7munJIlKCVkFCYY+p3ErYFXCjmFjnfTTRSC1OHWQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

<div id="app"></div>

© www.soinside.com 2019 - 2024. All rights reserved.