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

React+TS编写轮播图

当前轮播图存在部分问题,一次循环结束,进入下一次需要点击两次(所以动画效果上点击第二次才出现)


轮播图:实现无限循环轮播图的关键在于"视觉欺骗"——我们在实际数据的前后各添加部分数据副本,当滚动到边缘时快速而无缝地跳转到另一端,从而创造出无限循环的视觉效果。

理想效果

轮播图理想效果:呈现多个元素盒子,并且首元素默认初次呈现居中效果,通过左右按钮控制轮播图的滑动,滑动一次下一个元素又再次居中,居中元素有一个居中动画效果

静态效果:

逻辑思路

初始准备

  1. 首先在scss里面将track盒子居中,最外层盒子设置overflow:hidden,注意:这里尽量不要去使用transform去让track居中,不然后续ts去控制盒子移动这个效果会被抵消
  2. 当前居中的元素并非首元素,是track盒子里中的中间元素,给track中间数据的midOder标记为为0因为这是实际的中间元素
  3. 想要首元素居中,在初始化的时候需要进行一次transform去移动使首元素居中

控制移动

  1. 计算滑动距离=两个盒子的left距离,这里采用clienWidth因为在我自己项目中是响应式布局,使用clienWidth更适合
  2. 然后给左右移动按钮添加点击事件,去更新currentIndex
  3. 普通移动:添加移动效果动画,并且移动currentIdex*sliWidth(transform的效果是覆盖的,会覆盖初始化的首元素为中点,所以track真实的位置初始是真实中间元素是起点也就是midOder为0的元素是起点,所以是相对于这个起点进行的移动)

无限循环效果

  1. 正常普通移动到第一个克隆dom,然后下一次点击transition为none,视觉上用户看不到已经移动到了下一次循环中
  2. 然后调用setCurentIndex去更新当前中间元素标记
  3. 与前面普通移动放在一起,形成判断条件,到达了边缘判断,就进行视觉欺骗

添加中间动画

  1. 判断当前中间位置currentIndex是否等于元素的midOrder,是的话添加中间效果动画

数据结构准备

const carouselData = [{title: '00',midOrder: -2,},{title: '11',midOrder: -1,},{title: '22',midOrder: 0,},{title: '33',midOrder: 1,},{title: '44',midOrder: 2,},
];

组件实现步骤

1. 扩展数据创建"视觉循环"

const slides = [carouselData[carouselData.length - 3],carouselData[carouselData.length - 2],carouselData[carouselData.length - 1],...carouselData,carouselData[0],carouselData[1],carouselData[2],
];

在原始数据前后各添加3个数据项,这样当滚动到"边缘"时,可以无缝跳转。

2. 状态管理

const [currentIndex, setCurrentIndex] = useState(-2);
const [slideWidth, setSlideWidth] = useState(0);
const trackRef = useRef<HTMLDivElement>(null);
  • currentIndex 表示当前中心项的索引

  • slideWidth 存储每个轮播项的宽度

  • trackRef 用于操作轮播轨道DOM元素

3. 计算轮播项宽度

useEffect(() => {const items = trackRef.current?.querySelectorAll('.activities-recent-item');if (!items || items.length < 2) return;
​const first = items[0].getBoundingClientRect();const second = items[1].getBoundingClientRect();setSlideWidth(first.left - second.left);
}, []);

这个效果通过比较相邻两个轮播项的位置来计算单个项的宽度。

4. 处理导航点击

const handleDirection = (dir: 'left' | 'right') => {if (dir === 'left') {setCurrentIndex((prev) => prev - 1);} else {setCurrentIndex((prev) => prev + 1);}
};

点击左右按钮时,更新当前索引。

5. 无限循环修正

useEffect(() => {const track = trackRef.current;if (!track) return;
​if (currentIndex === -4) {track.style.transition = 'none';track.style.transform = `translateX(${2 * slideWidth}px)`;setCurrentIndex(2);} else if (currentIndex === 4) {track.style.transition = 'none';track.style.transform = `translateX(${-2 * slideWidth}px)`;setCurrentIndex(-2);} else {track.style.transition = 'transform 0.4s ease';track.style.transform = `translateX(${currentIndex * slideWidth}px)`;}
}, [currentIndex]);

当滚动到边缘时:

  1. 禁用过渡动画

  2. 立即跳转到另一端

  3. 重新启用动画

6. 渲染组件

return (<><div className="rencent-to-left recent-to-button" onClick={() => handleDirection('left')}><i className="iconfont icon-zuojiantou"></i></div>
​<div className="activities-recent-container"><div ref={trackRef} className="activities-recent-box track-box">{slides.map((item) => (<div className={`activities-recent-item ${item.midOrder === currentIndex ? 'mid-active' : ''}`}>{item.title}</div>))}</div></div>
​<div className="rencent-to-right recent-to-button" onClick={() => handleDirection('right')}><i className="iconfont icon-youjiantou"></i></div></>
);

关键点总结

  1. 数据扩展:通过在原始数据前后添加副本,实现视觉上的无限循环

  2. 无缝跳转:当滚动到边缘时,禁用动画并立即跳转

  3. 精确计算:动态计算轮播项宽度确保滚动精度

  4. 状态管理:使用React状态控制当前显示项

  5. CSS过渡:通过CSS实现平滑的滚动效果

 

相关文章:

  • 计算机视觉cv入门之Haarcascade的基本使用方法(人脸识别为例)
  • 【后端】【Django】Django 模型中的 `clean()` 方法详解:数据校验的最后防线
  • 【人工智能】推荐开源企业级OCR大模型InternVL3
  • css3新特性第四章(渐变)
  • 【条形码识别改名工具】如何批量识别图片条形码,并以条码内容批量重命名,基于WPF和Zxing的开发总结
  • 【iOS】alloc init new底层原理
  • 嵌入式---零点漂移(Zero Drift)
  • 网络设备基础运维全攻略:华为/思科核心操作与巡检指南
  • IDEA多环节实现优雅配置
  • IDEA在Git提交时添加.ignore忽略文件,解决为什么Git中有时候使用.gitignore也无法忽略一些文件
  • 国际数据加密算法(IDEA)详解
  • 按字符串长度升序,长度相同则按字典序
  • 【Linux系统】Linux基础指令(详解Linux命令行常用指令,每一个指令都有示例演示)
  • 30天开发操作系统 第26天 -- 为窗口移动提速
  • 实现AWS Data Pipeline安全地请求企业内部API返回数据
  • 2026《数据结构》考研复习笔记四(第一章)
  • 蓝桥杯 二进制问题 刷题笔记
  • Linux操作系统简介:从开源内核到技术生态
  • BeautifulSoup 库的使用——python爬虫
  • AWS EC2完全指南:如何快速搭建高性能云服务器?
  • 第1现场|俄乌互指对方违反复活节临时停火提议
  • 累计亏损10亿元,桂林旅游怎么了?
  • 马拉松夺冠机器人将小批量量产:价格与一台入门级小轿车差不多
  • 北京理工大学:教师宫某涉嫌师德失范,暂停其一切职务活动
  • 观察|如何推动再保险交易规模上量增加话语权,行业在临港新片区共倡议
  • “80后”辽宁石油化工大学副校长杨占旭已任阜新市领导