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

React.js中点击Swiper图片或全屏图标如何实现幻灯片全屏预览

实现方案

方案1:基于现有Swiper 6.5.1改造(无需新增依赖)

改造步骤

  • 新增2个状态变量:控制全屏模态框显隐的isFullscreen、记录当前激活轮播项索引的activeSlideIndex
  • 给现有主轮播图、缩略图绑定点击事件,点击时触发全屏开启,同步当前激活的轮播索引;可自行添加全屏图标按钮作为额外触发入口
  • 新增全屏模态框DOM结构,仅在isFullscreen为true时渲染,内部复用Swiper主图+缩略图的逻辑,默认定位到当前激活的轮播项,同时添加关闭按钮、ESC键关闭的适配
  • 补充全屏场景下的样式,让轮播容器占满整个视口,缩略图固定在底部展示

修改后代码

App.js
import React, { useState, useEffect } from 'react';
import { Swiper, SwiperSlide } from 'swiper/react';
import SwiperCore, { Navigation, Pagination, Controller, Thumbs } from 'swiper';
import 'swiper/swiper-bundle.css';
import './styles.css';

SwiperCore.use([Navigation, Pagination, Controller, Thumbs]);
   
function App() {
  const [thumbsSwiper, setThumbsSwiper] = useState(null);
  const [controlledSwiper, setControlledSwiper] = useState(null);
  // 新增状态
  const [isFullscreen, setIsFullscreen] = useState(false);
  const [activeSlideIndex, setActiveSlideIndex] = useState(0);
  const [fullscreenThumbs, setFullscreenThumbs] = useState(null);

  const slides = [];
  for (let i = 0; i < 5; i += 1) {
    slides.push(
      <SwiperSlide key={`slide-${i}`} tag="li">
        <img
          src={`http://localhost:3000/logo512.png`}
          style={{ listStyle: 'none', cursor: 'pointer' }}
          alt={`Slide ${i}`}
          onClick={() => {
            setActiveSlideIndex(i);
            setIsFullscreen(true);
          }}
        />
      </SwiperSlide>
    );
  }

  const thumbs = [];
  for (let i = 0; i < 5; i += 1) {
    thumbs.push(
      <SwiperSlide key={`thumb-${i}`} tag="li" style={{ listStyle: 'none', cursor: 'pointer' }}>
        <img
          src={`http://localhost:3000/logo192.png`}
          alt={`Thumbnail ${i}`}
          onClick={() => {
            setActiveSlideIndex(i);
            setIsFullscreen(true);
          }}
        ></img>
      </SwiperSlide>
    );
  }

  // ESC键关闭全屏
  useEffect(() => {
    const handleEsc = (e) => {
      if (e.keyCode === 27) setIsFullscreen(false);
    };
    if (isFullscreen) {
      document.addEventListener('keydown', handleEsc);
      // 禁止背景滚动
      document.body.style.overflow = 'hidden';
    }
    return () => {
      document.removeEventListener('keydown', handleEsc);
      document.body.style.overflow = 'auto';
    };
  }, [isFullscreen]);

 
  return (
    <React.Fragment>
      {/* 原有普通轮播 */}
      <div style={{ position: 'relative' }}>
        <button 
          className="fullscreen-trigger"
          onClick={() => setIsFullscreen(true)}
          style={{ position: 'absolute', top: 10, right: 10, zIndex: 10, cursor: 'pointer' }}
        >
          []
        </button>
        <Swiper
          id="main"
          thumbs={{ swiper: thumbsSwiper }}
          controller={{ control: controlledSwiper }}
          tag="section"
          wrapperTag="ul"
          navigation
          pagination
          spaceBetween={0}
          slidesPerView={1}
          initialSlide={activeSlideIndex}
          onInit={(swiper) => console.log('Swiper initialized!', swiper)}
          onSlideChange={(swiper) => {
            console.log('Slide index changed to: ', swiper.activeIndex);
            setActiveSlideIndex(swiper.activeIndex);
          }}
          onReachEnd={() => console.log('Swiper end reached')}
        >
          {slides}
        </Swiper>

        <Swiper
          id="thumbs"
          spaceBetween={5}
          slidesPerView={3}
          onSwiper={setThumbsSwiper}
        >
          {thumbs}
        </Swiper>
      </div>

      {/* 全屏模态框 */}
      {isFullscreen && (
        <div className="fullscreen-modal">
          <button 
            className="fullscreen-close"
            onClick={() => setIsFullscreen(false)}
            style={{ position: 'absolute', top: 20, right: 20, zIndex: 100, color: '#fff', fontSize: 24, background: 'none', border: 'none', cursor: 'pointer' }}
          >
            ×
          </button>
          <Swiper
            id="fullscreen-main"
            thumbs={{ swiper: fullscreenThumbs }}
            tag="section"
            wrapperTag="ul"
            navigation
            spaceBetween={0}
            slidesPerView={1}
            initialSlide={activeSlideIndex}
            onSlideChange={(swiper) => setActiveSlideIndex(swiper.activeIndex)}
          >
            {slides}
          </Swiper>

          <Swiper
            id="fullscreen-thumbs"
            spaceBetween={5}
            slidesPerView={5}
            onSwiper={setFullscreenThumbs}
            style={{ position: 'absolute', bottom: 20, left: '50%', transform: 'translateX(-50%)', width: '80%' }}
          >
            {thumbs}
          </Swiper>
        </div>
      )}
    </React.Fragment>
  );
}

export default App;
styles.css新增内容
/* 原有样式保留,新增以下内容 */
.fullscreen-modal {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background: rgba(0,0,0,0.9);
  z-index: 9999;
}

#fullscreen-main {
  width: 100%;
  height: 85vh;
}

#fullscreen-main img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

#fullscreen-thumbs .swiper-slide {
  opacity: 0.6;
}

#fullscreen-thumbs .swiper-slide-thumb-active {
  opacity: 1;
  border: 2px solid #fff;
}

方案2:使用第三方组件快速实现

如果不需要自定义复杂逻辑,可以直接使用npm平台的react-image-gallery组件,原生支持带缩略图的全屏预览能力,只需传入图片数组配置即可快速实现需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 04:45:06