当前位置:首页 > 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 中的动画衰减效果实现 在 React 中实现衰减效果(如滚动衰减、拖动释放后的惯性滑动)通常需要结合物理动画原理或第三方动画库。以下是几种常见方法: 使用 CSS 动画和 @keyfra…

react如何收录

react如何收录

React 收录方法 React 的收录主要涉及搜索引擎优化(SEO)和预渲染技术。由于 React 是单页应用(SPA),默认情况下内容由 JavaScript 动态生成,可能导致搜索引擎爬虫难以收…

react如何拓展

react如何拓展

React 拓展方法 使用高阶组件(HOC) 高阶组件是一种复用组件逻辑的方式,通过接收一个组件并返回一个新组件实现功能拓展。例如,为组件添加日志功能: function withLogging…

react如何打包

react如何打包

打包 React 项目的基本步骤 React 项目通常使用 create-react-app 或类似的脚手架工具创建,这些工具内置了打包功能。以下是打包 React 项目的详细方法: 安装依赖并构建…

react如何检测

react如何检测

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

react如何刷新

react如何刷新

刷新React组件的方法 使用状态更新触发重新渲染 通过更新组件的状态可以触发重新渲染。React会在状态变化时自动重新渲染组件。 const [count, setCount] = useStat…