当前位置:首页 > 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 moment如何使用

react moment如何使用

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

如何改造react

如何改造react

改造 React 项目的关键方法 分析当前项目结构 通过评估现有组件、状态管理和依赖项,明确需要改进的部分。使用工具如 webpack-bundle-analyzer 识别性能瓶颈。 升级 Reac…

react如何遍历

react如何遍历

遍历数组或对象的方法 在React中,遍历数组或对象通常用于渲染列表或动态生成内容。以下是几种常见的遍历方法: 使用map遍历数组map是遍历数组并返回新数组的高阶函数,适合渲染列表。…

react如何检测

react如何检测

检测 React 应用的方法 使用 PropTypes 进行类型检查 PropTypes 是 React 内置的类型检查工具,用于验证组件的 props 是否符合预期。在开发环境中,PropTypes…

react如何重置

react如何重置

重置 React 应用的状态 使用 useState 钩子重新初始化状态变量是最直接的方法。将状态变量重置为初始值或空值即可完成重置。 const [count, setCount] = useSt…

react如何同步修改

react如何同步修改

同步修改状态的常见方法 在React中同步修改状态通常涉及使用useState或useReducer钩子,结合React的批处理机制确保状态更新的一致性。以下是几种典型场景的解决方案: 直接使用us…