React滑块组件Inner Slider循环序列异常的修复方案咨询
解决方案
问题核心是Inner Slider仅依赖原数组做滑动偏移,导致元素被移出容器后无法循环补充。要实现预期的循环序列,需要通过扩展数据源+无缝状态重置来实现。
关键修改点
- 复制图片数组,让Inner Slider的数据源变为
[...image, ...image],保证滑动时能衔接后续元素 - 修正偏移计算逻辑,确保每次滑动都显示连续的三张图
- 优化定时器逻辑,避免无限触发和内存泄漏
- 当
current达到原数组长度时,无缝重置状态,保持轮播连续性
修改后的完整代码
import React, { useEffect, useState } from "react"; import { motion, AnimatePresence } from "framer-motion"; const image = [ { banner: "https://image.tmdb.org/t/p/original/sRLC052ieEzkQs9dEtPMfFxYkej.jpg", poster: "https://image.tmdb.org/t/p/original/ui4DrH1cKk2vkHshcUcGt2lKxCm.jpg" }, { banner: "https://image.tmdb.org/t/p/original/4HodYYKEIsGOdinkGi2Ucz6X9i0.jpg", poster: "https://image.tmdb.org/t/p/original/ui4DrH1cKk2vkHshcUcGt2lKxCm.jpg" }, { banner: "https://image.tmdb.org/t/p/original/1jITxVJhkiFJuQuj8NcPLmDNtJg.jpg", poster: "https://image.tmdb.org/t/p/original/qjhahNLSZ705B5JP92YMEYPocPz.jpg" } ]; export default function Carousel() { const [current, setCurrent] = useState(0); const [isTransitioning, setIsTransitioning] = useState(false); const imageLength = image.length; const nextImage = function () { if (isTransitioning) return; if (current === imageLength - 1) { // 滑到原数组末尾时,完成动画后无缝重置状态 setIsTransitioning(true); setTimeout(() => { setCurrent(0); setIsTransitioning(false); }, 300); // 匹配动画过渡时长 } else { setCurrent(prev => prev + 1); } }; useEffect(() => { const timer = setTimeout(() => { nextImage(); }, 2000); return () => clearTimeout(timer); // 清理定时器,避免内存泄漏 }, [current, isTransitioning]); const variants = { initial: { x: 1000, opacity: 0, }, animate: { x: 0, opacity: 1, transition: { x: { type: "spring", stiffness: 300, damping: 30 }, opacity: { duration: 0.2 }, }, }, exit: { x: -1000, opacity: 0, transition: { x: { type: "spring", stiffness: 300, damping: 30 }, opacity: { duration: 0.2 }, }, }, }; return ( <div className="w-full h-[550px] overflow-hidden relative"> <AnimatePresence initial={false} > <motion.img variants={variants} animate="animate" initial="initial" exit="exit" alt="slides" key={image[current]?.banner} className="slides z-20 absolute inset-0 w-full h-full object-cover" src={image[current]?.banner} /> <div className="absolute w-[40%] h-auto overflow-hidden justify-center top-1/2 translate-y-[-50%] gap-4 m-auto flex right-8 z-40" > {/* Inner Slider - 用双数组实现循环展示 */} {[...image, ...image].map((items, index) => ( <motion.img src={items?.poster} key={index} className="w-[30%] object-cover" alt="" animate={{ x: isTransitioning ? 0 : `calc(-${current * 100}% - ${current}rem)`, transition: isTransitioning ? { duration: 0 } : {} }} /> ))} </div> </AnimatePresence> </div> ); }
效果说明
- 双数组数据源:
[...image, ...image]让Inner Slider拥有6个元素,滑动到原数组末尾时,复制的元素会衔接上来,视觉上形成[img1,img2,img3]→[img2,img3,img1]→[img3,img1,img2]的循环序列。 - 无缝重置:当
current到达原数组最后一位时,先完成滑动动画,再瞬间重置current为0并关闭过渡动画,避免出现跳变。 - 定时器优化:添加清理函数防止内存泄漏,依赖
current和isTransitioning确保轮播节奏稳定。
内容的提问来源于stack exchange,提问作者Arnab Mukherjee
相关产品推荐
相关产品推荐

