当前位置: 首页 > news >正文

react实现无缝轮播组件

1.组件定义

import React, { useState, useEffect, useCallback } from "react";
import "./style.component.css";interface SeamlessCarouselProps {imageList: string[];autoPlaying?: boolean;
}const SeamlessCarousel: React.FC<SeamlessCarouselProps> = ({imageList,autoPlaying = true,
}) => {const [currentIndex, setCurrentIndex] = useState(1); const [isTransitioning, setIsTransitioning] = useState(true);const [isAutoPlaying, setIsAutoPlaying] = useState(autoPlaying);const [isPaused, setIsPaused] = useState(false);const extendedImages = [imageList[imageList.length - 1],...imageList,imageList[0],];const nextSlide = useCallback(() => {setCurrentIndex((prev) => {if (prev >= extendedImages.length - 1) {return prev;}return prev + 1;});setIsTransitioning(true);}, []);const prevSlide = () => {setCurrentIndex((prev) => {if (prev <= 0) {return prev;}return prev - 1;});setIsTransitioning(true);};useEffect(() => {if (!isAutoPlaying || isPaused) return;if (!isAutoPlaying) return;const interval = setInterval(nextSlide, 3000);return () => clearInterval(interval);}, [isAutoPlaying, isPaused, nextSlide]);useEffect(() => {if (currentIndex === extendedImages.length - 1) {const timeout = setTimeout(() => {setIsTransitioning(false);setCurrentIndex(1);}, 500);return () => clearTimeout(timeout);}if (currentIndex === 0) {const timeout = setTimeout(() => {setIsTransitioning(false);setCurrentIndex(imageList.length);}, 500);return () => clearTimeout(timeout);}setIsTransitioning(true);}, [currentIndex, extendedImages.length, imageList.length]);return (<divclassName={`carousel-container ${isPaused ? "show-arrows" : ""}`}onMouseEnter={() => setIsPaused(true)}onMouseLeave={() => setIsPaused(false)}><divclassName="carousel-list"style={{transform: `translateX(-${currentIndex * 100}%)`,transition: isTransitioning? "transform 0.5s ease": "none",}}>{extendedImages.map((image, index) => (<divkey={index}className="carousel-item"style={{ backgroundImage: `url(${image})` }}></div>))}</div><divclassName="carousel-arrow carousel-arrow-left"onClick={prevSlide}><span className="arrow-left"></span></div><divclassName="carousel-arrow carousel-arrow-right"onClick={nextSlide}><span className="arrow-right"></span></div><div className="circles-container">{imageList.map((_, index) => (<spankey={index}className={`circle ${index === currentIndex - 1 ? "active" : ""}`}onClick={() => setCurrentIndex(index + 1)}></span>))}</div><div className="autoplay-control"><button onClick={() => setIsAutoPlaying(!isAutoPlaying)}>{isAutoPlaying ? "暂停" : "播放"}</button></div></div>);
};export default SeamlessCarousel;

2.样式设置

.carousel-container {display: flex;position: relative;align-items: center;justify-content: center;scroll-behavior: smooth;outline: 1px solid #dddedc;border-radius: 10px;width: 900px;height: 600px;margin: 30px auto;overflow: hidden;
}.carousel-list {display: flex;position: relative;height: 100%;width: 100%;scroll-snap-align: start;aspect-ratio: 5 / 3;
}.carousel-item {flex: 0 0 100%;height: 100%;background-size: cover;background-repeat: no-repeat;background-position: center;
}.carousel-arrow {position: absolute;width: 40px;height: 40px;border-radius: 50%;background: rgba(255, 255, 255, 0.7);display: flex;align-items: center;justify-content: center;cursor: pointer;z-index: 10;transition: opacity 0.3s ease, background 0.3s ease;opacity: 0;
}.carousel-container.show-arrows .carousel-arrow {opacity: 1; /* 悬停时显示 */
}.carousel-arrow:hover {background: rgba(255, 255, 255, 0.9);
}.carousel-arrow-left {left: 10px;
}.carousel-arrow-right {right: 10px;
}.arrow-left,
.arrow-right {width: 12px;height: 12px;border-top: 2px solid #333;border-right: 2px solid #333;
}.arrow-left {transform: rotate(-135deg);margin-left: 4px;
}.arrow-right {transform: rotate(45deg);margin-right: 4px;
}/* 圆点指示器 */
.circles-container {display: flex;position: absolute;bottom: 20px;left: 50%;transform: translateX(-50%);gap: 20px;
}.circle {display: block;width: 24px;height: 24px;border-radius: 50%;background: transparent;border:1px solid rgba(255, 255, 255, 0.7);cursor: pointer;transition: all 0.3s ease;
}.circle.active {background-color: rgb(249, 246, 246);border-color: white;
}.circle:hover {background-color: rgba(255, 255, 255, 0.5);
}.autoplay-control {position: absolute;top: 15px;right: 15px;
}.autoplay-control button {background: rgba(0, 0, 0, 0.2);color: white;border: none;padding: 5px 10px;border-radius: 4px;cursor: pointer;
}.autoplay-control button:hover {background: rgba(0, 0, 0, 0.7);
}

3.组件使用

import SeamlessCarousel from "@/components/carousel/SeamlessMo"import one from "@/components/carousel/img/abstract-2512412.jpg";
import two from "@/components/carousel/img/ai-generated-8061340.jpg";
import three from "@/components/carousel/img/asian-422700.jpg";
import four from "@/components/carousel/img/binary-978942.jpg";
import five from "@/components/carousel/img/code-113611.jpg";
import six from "@/components/carousel/img/fruit-7048114.jpg";
import seven from "@/components/carousel/img/moss-4930309.jpg";
import eight from "@/components/carousel/img/wood-591631.jpg";const sampleImages = [one, two, three, four, five, six, seven, eight];const CarouselPage: React.FC = () => {return (<><h1>无缝轮播页面</h1><div className="mb-4"><SeamlessCarousel imageList={sampleImages} autoPlaying={false} /></div></>)
}export default CarouselPage;

4.使用测试

需要用到的图片请自行放到对应的目录,再将图片换成实际的路径即可。


文章转载自:

http://8QqsxMLp.zphLb.cn
http://Y4FE1tuM.zphLb.cn
http://ZmCrbeRk.zphLb.cn
http://vjdEEcCP.zphLb.cn
http://zPe2QbI3.zphLb.cn
http://k9IFCOb7.zphLb.cn
http://c1RSO2eU.zphLb.cn
http://zS0cH4mk.zphLb.cn
http://WO7WVVGr.zphLb.cn
http://uSIi9poh.zphLb.cn
http://hpMMopid.zphLb.cn
http://BUs8Cewr.zphLb.cn
http://uX5GoTTE.zphLb.cn
http://2iqQSFOD.zphLb.cn
http://Cfi2OrRr.zphLb.cn
http://ICvStzJo.zphLb.cn
http://ClyLxYzL.zphLb.cn
http://fYHfIUCM.zphLb.cn
http://HXVfGybt.zphLb.cn
http://6OnS6Brr.zphLb.cn
http://8Sheea1r.zphLb.cn
http://GZaPerAG.zphLb.cn
http://31vR6Szf.zphLb.cn
http://A7wQBboR.zphLb.cn
http://UhpbfU5y.zphLb.cn
http://PpdBvwsb.zphLb.cn
http://N6OLe7vp.zphLb.cn
http://ESly4roi.zphLb.cn
http://33VZNLCS.zphLb.cn
http://jHZLXMEf.zphLb.cn
http://www.dtcms.com/a/378280.html

相关文章:

  • DbGate数据库管理新方案:cpolar打造跨平台远程访问通道
  • Spark+Hive中间件
  • 【案例分享】TeeChart 助力 Softdrill 提升油气钻井数据可视化能力
  • 在图形 / 游戏开发中,为何 Pixels Per Unit(PPU)数值越小,物体在屏幕上显示的尺寸越大?
  • new和mallo的区别
  • mysql中%前置模糊查询怎么优化
  • 单串口服务器-工业级串口联网解决方案
  • 使用 Tkinter + Requests 实现地理信息安全系统学习时长助手
  • 多语言共享贩卖机投资理财共享售卖机投资理财系统
  • 京东JDS 测评图形规律题答题技巧
  • 打工人日报#20250911
  • 一、WPF入门介绍+Grid和StackPanel布局介绍+实战模拟Notepad++页面布局
  • 电商平台用户流失预测与干预机制
  • 华为网路设备学习-33(BGP协议 八)BGP路由 选路规则
  • 【科研绘图系列】R语言绘制海洋微生物群落动态分析
  • 基于微服务架构的电商返利APP技术架构设计与性能优化策略
  • Java开发入门指南:IDE选择与数据库连接详解
  • 【算法】栈专题
  • hadoop的api操作对象存储
  • 硬件开发_基于物联网的沼气池环境监测系统
  • 水质在线监测系统御控物联网解决方案
  • A股大盘数据-20250911分析
  • 【星海出品】rabbitMQ - 叁 应用篇
  • 【npm】npm 包更新工具 npm-check-updates (ncu)
  • pnpm相对于npm,yarn的优势
  • vue3源码学习(四)watch 源码学习
  • 利用JSONCrack与cpolar提升数据可视化及跨团队协作效率
  • 短剧小程序系统开发:打造个性化娱乐新平台
  • 从MySQL到StarRocks:全量与增量同步的最佳实践
  • 第七篇:识破“共因失效”——如何阻止汽车系统的“团灭”危机