当前位置:首页 > React

react实现循环滚动

2026-01-27 07:23:37React

实现循环滚动的几种方法

使用CSS动画结合React状态管理

import React, { useState, useEffect } from 'react';
import './ScrollComponent.css';

const ScrollComponent = ({ items }) => {
  const [currentIndex, setCurrentIndex] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => {
      setCurrentIndex((prevIndex) => (prevIndex + 1) % items.length);
    }, 3000);
    return () => clearInterval(interval);
  }, [items.length]);

  return (
    <div className="scroll-container">
      <div 
        className="scroll-content"
        style={{ transform: `translateY(-${currentIndex * 100}px)` }}
      >
        {items.map((item, index) => (
          <div key={index} className="scroll-item">{item}</div>
        ))}
        {/* 复制第一个元素实现无缝循环 */}
        <div className="scroll-item">{items[0]}</div>
      </div>
    </div>
  );
};

CSS样式示例

.scroll-container {
  height: 100px;
  overflow: hidden;
  position: relative;
}

.scroll-content {
  transition: transform 0.5s ease-in-out;
}

.scroll-item {
  height: 100px;
  display: flex;
  align-items: center;
  justify-content: center;
}

使用第三方库react-slick

安装react-slick

npm install react-slick slick-carousel

实现循环滚动组件

import React from 'react';
import Slider from 'react-slick';
import 'slick-carousel/slick/slick.css';
import 'slick-carousel/slick/slick-theme.css';

const AutoScrollCarousel = ({ items }) => {
  const settings = {
    dots: false,
    infinite: true,
    speed: 500,
    slidesToShow: 1,
    slidesToScroll: 1,
    autoplay: true,
    autoplaySpeed: 2000,
    vertical: true,
    verticalSwiping: true
  };

  return (
    <Slider {...settings}>
      {items.map((item, index) => (
        <div key={index}>
          <h3>{item}</h3>
        </div>
      ))}
    </Slider>
  );
};

使用requestAnimationFrame实现高性能滚动

import React, { useRef, useEffect } from 'react';

const SmoothScroller = ({ items }) => {
  const containerRef = useRef(null);
  const contentRef = useRef(null);
  const animationRef = useRef(null);
  const scrollSpeed = 50; // 像素/秒

  useEffect(() => {
    let position = 0;
    const containerHeight = containerRef.current.clientHeight;
    const contentHeight = contentRef.current.clientHeight;

    const animate = (timestamp) => {
      position += scrollSpeed / 60;

      if (position >= contentHeight - containerHeight) {
        position = 0;
      }

      contentRef.current.style.transform = `translateY(-${position}px)`;
      animationRef.current = requestAnimationFrame(animate);
    };

    animationRef.current = requestAnimationFrame(animate);

    return () => {
      cancelAnimationFrame(animationRef.current);
    };
  }, []);

  return (
    <div ref={containerRef} style={{ height: '200px', overflow: 'hidden' }}>
      <div ref={contentRef}>
        {items.map((item, index) => (
          <div key={index} style={{ height: '50px' }}>{item}</div>
        ))}
        {/* 复制内容实现无缝循环 */}
        {items.map((item, index) => (
          <div key={`copy-${index}`} style={{ height: '50px' }}>{item}</div>
        ))}
      </div>
    </div>
  );
};

横向循环滚动的实现

const HorizontalScroller = ({ items }) => {
  const [scrollPosition, setScrollPosition] = useState(0);
  const containerRef = useRef(null);
  const contentRef = useRef(null);

  useEffect(() => {
    const containerWidth = containerRef.current.clientWidth;
    const contentWidth = contentRef.current.scrollWidth / 2;
    let animationId;

    const scroll = () => {
      setScrollPosition(prev => {
        const newPos = (prev + 1) % contentWidth;
        return newPos;
      });
      animationId = requestAnimationFrame(scroll);
    };

    animationId = requestAnimationFrame(scroll);

    return () => {
      cancelAnimationFrame(animationId);
    };
  }, []);

  return (
    <div ref={containerRef} style={{ overflow: 'hidden', whiteSpace: 'nowrap' }}>
      <div 
        ref={contentRef}
        style={{ 
          display: 'inline-block',
          transform: `translateX(-${scrollPosition}px)`
        }}
      >
        {[...items, ...items].map((item, index) => (
          <span key={index} style={{ padding: '0 20px' }}>{item}</span>
        ))}
      </div>
    </div>
  );
};

性能优化建议

  • 使用will-change属性优化渲染性能

    .scroll-content {
    will-change: transform;
    }
  • 对于大量数据,考虑虚拟滚动技术

  • 避免频繁的DOM操作,使用transform代替top/left定位

  • 合理设置requestAnimationFrame的调用频率

  • 移除不可见的元素时使用CSS opacity而非display:none

react实现循环滚动

标签: react
分享给朋友:

相关文章

react 如何执行

react 如何执行

安装 React 确保 Node.js 安装在本地环境中。通过以下命令创建新的 React 项目: npx create-react-app my-app 进入项目目录并启动开发服务器:…

react native如何启动

react native如何启动

如何启动 React Native 项目 安装 Node.js 和 npm 确保已安装 Node.js(建议版本 16 或更高)和 npm(Node.js 自带)。可通过以下命令检查版本: nod…

react 如何执行

react 如何执行

安装 Node.js 和 npm React 开发需要 Node.js 环境,因为它提供了 npm(或 yarn)包管理工具。从 Node.js 官网 下载并安装最新 LTS 版本。安装完成后,在终端…

如何生成react代码

如何生成react代码

使用 Create React App 生成项目 安装 Node.js 后,通过命令行工具运行以下命令创建新项目: npx create-react-app my-app cd my-app npm…

react moment如何使用

react moment如何使用

安装 react-moment 通过 npm 或 yarn 安装 react-moment: npm install react-moment 或 yarn add react-moment…

如何降低react版本

如何降低react版本

降低 React 项目版本的步骤 检查当前 React 版本 运行以下命令查看项目中安装的 React 当前版本: npm list react 或 yarn list react 修改…