You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React-Multi-Carousel无限模式下slideIndex异常及居中放大轮播问题

解决react-multi-carousel无限轮播下索引异常问题并实现中间项放大效果

问题根源

开启infinite模式后,react-multi-carousel会自动在原始轮播项的首尾添加重复项以实现无缝滚动,导致beforeChange回调返回的nextSlide/current索引是基于扩展后的数组,而非原始数据的真实索引,进而无法正确控制轮播项的样式逻辑。

核心解决方案:计算真实索引

通过取模运算将扩展数组的索引转换为原始数据的真实索引,同时处理向左滚动到复制项时的负数索引边界情况:

  1. 先获取原始轮播项的总长度:
const itemCount = data?.banners?.length || 0;
  1. 编写索引转换函数:
const getRealIndex = (index, totalItems) => {
  if (totalItems === 0) return 0;
  let realIndex = index % totalItems;
  // 处理向左滚动到复制项时的负数索引
  return realIndex < 0 ? realIndex + totalItems : realIndex;
};
  1. 修改beforeChange回调,存储真实索引:
beforeChange={(nextSlide, current) => {
  const realNextIndex = getRealIndex(nextSlide, itemCount);
  setSlideIndex(realNextIndex);
}}

实现中间激活项放大效果

结合centerMode和自定义样式,实现示例图的中间项突出效果:

  1. 开启centerMode并调整响应式配置:
const responsiveCarouselTournamentBanner = {
  mobile: {
    breakpoint: { max: 464, min: 0 },
    items: 1.5 // 移动端显示1个完整项+左右各半个项
  },
  tablet: {
    breakpoint: { max: 768, min: 465 },
    items: 2.5
  },
  desktop: {
    breakpoint: { max: Infinity, min: 769 },
    items: 3 // 桌面端显示3个项,中间为激活项
  }
};

// 在Carousel组件中开启centerMode
<Carousel
  // ...其他属性
  centerMode={true}
  // ...
>
  1. 给激活项添加特殊样式:
    修改轮播项的className,根据真实索引判断是否为激活项:
{data?.banners?.map((item, index) => (
  <img
    key={index}
    src={item || "/images/tournament-img-default.png"}
    className={`w-full max-w-[90%] h-[210px] md:max-w-[858px] md:h-[482px] object-cover mx-auto rounded-xl banner-primary-color ${slideIndex === index ? 'active-slide' : ''}`}
    alt="dgg-banner"
  />
))}
  1. 添加CSS样式:
/* 轮播项容器基础样式 */
.custom-item-class {
  display: flex;
  justify-content: center;
  align-items: center;
  transition: transform 0.3s ease;
}

/* 激活项放大 */
.active-slide {
  transform: scale(1.1);
  z-index: 1;
}

/* 非激活项缩小 */
.custom-item-class:not(.active-slide) {
  transform: scale(0.9);
  opacity: 0.8;
}

完整代码示例

import Carousel from 'react-multi-carousel';
import 'react-multi-carousel/lib/styles.css';
import { useState } from 'react';

const TournamentBanner = ({ data }) => {
  const [slideIndex, setSlideIndex] = useState(0);
  const itemCount = data?.banners?.length || 0;

  const responsiveCarouselTournamentBanner = {
    mobile: {
      breakpoint: { max: 464, min: 0 },
      items: 1.5
    },
    tablet: {
      breakpoint: { max: 768, min: 465 },
      items: 2.5
    },
    desktop: {
      breakpoint: { max: Infinity, min: 769 },
      items: 3
    }
  };

  const getRealIndex = (index, totalItems) => {
    if (totalItems === 0) return 0;
    let realIndex = index % totalItems;
    return realIndex < 0 ? realIndex + totalItems : realIndex;
  };

  return (
    <Carousel
      className="relative"
      responsive={responsiveCarouselTournamentBanner}
      autoPlaySpeed={3000}
      infinite
      arrows={false}
      itemClass="custom-item-class"
      centerMode={true}
      slidesToSlide={1}
      beforeChange={(nextSlide, current) => {
        const realNextIndex = getRealIndex(nextSlide, itemCount);
        setSlideIndex(realNextIndex);
      }}
    >
      {data?.banners?.map((item, index) => (
        <img
          key={index}
          src={item || "/images/tournament-img-default.png"}
          className={`w-full max-w-[90%] h-[210px] md:max-w-[858px] md:h-[482px] object-cover mx-auto rounded-xl banner-primary-color ${slideIndex === index ? 'active-slide' : ''}`}
          alt="dgg-banner"
        />
      ))}
    </Carousel>
  );
};

export default TournamentBanner;

内容的提问来源于stack exchange,提问作者Mohtep

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 06:35:30