SwiperJS + React:幻灯片失活时如何停止对应视频播放
Swiper多视频轮播问题修复方案
核心修改点
- 利用Swiper内置的幻灯片切换回调事件,统一管控所有视频的播放状态,切换时暂停所有非活动幻灯片内的视频,解决声音叠加问题
- 回调中读取当前活动幻灯片的真实索引(适配loop循环模式),同步更新useState存储的当前视频标题
- 初始化轮播时自动设置首个活动幻灯片的标题,避免初始状态值为空
关键逻辑说明
- 开启loop循环模式时,不要直接用返回对象的
activeIndex取值,要使用realIndex获取对应原始数组的真实索引,避免循环模式下克隆幻灯片导致索引匹配错误 - 视频选择器加专属类名限定范围,避免误选中页面其他位置的视频元素
- 非活动视频仅做暂停处理即可,用户手动点击播放时不受限制
完整修改后代码
import { Navigation, Pagination } from 'swiper' import { Swiper, SwiperSlide } from 'swiper/react' import 'swiper/css' import 'swiper/css/pagination' import { useState } from 'react' const slides = [ { videoPath: '/img/case-studies/snacklins/tiktoks/SNACKLINS_TikTok_HotGirlShit', title: 'Hot Girl Shit', }, { videoPath: '/img/case-studies/snacklins/tiktoks/SNACKLINS_TikTok_HowBizarre', title: 'How Bizarre', }, { videoPath: '/img/case-studies/snacklins/tiktoks/SNACKLINS_TikTok_NobleQuest', title: 'Noble Quest', }, ] function CaseStudies_TikTok() { const [activeTitle, setActiveTitle] = useState('') // 轮播视频专属类名,用于元素选择 const carouselVideoClass = 'carousel-video' // 幻灯片切换统一处理逻辑 const handleSlideChange = (swiper) => { const currentRealIndex = swiper.realIndex // 更新当前活动视频标题 setActiveTitle(slides[currentRealIndex].title) // 获取当前轮播下所有视频 const allVideos = swiper.el.querySelectorAll(`.${carouselVideoClass}`) allVideos.forEach((video, index) => { // 非当前活动视频暂停 if (index !== swiper.activeIndex) { video.pause() } // 如需切换后自动播放当前视频,放开下面注释即可 // else { // video.play().catch(() => {}) // } }) } function SetSlide({ slide }) { return ( <video controls muted={false} className={`h-full w-auto border-6 border-cream rounded-lg hover:cursor-grab ${carouselVideoClass}`} > <source src={`${slide.videoPath}.webm`} type='video/webm' /> <source src={`${slide.videoPath}.mp4`} type='video/mp4' /> </video> ) } const Carousel = () => { return ( <Swiper spaceBetween={20} slidesPerView={1.25} loop navigation={{ nextEl: '.carousel-button-next', prevEl: '.carousel-button-prev', }} pagination={{ clickable: true, el: '.carousel-pagination', type: 'fraction', }} modules={[Navigation, Pagination]} // 初始化时设置首个标题 onSwiper={(swiper) => { setActiveTitle(slides[swiper.realIndex].title) }} // 绑定切换事件 onSlideChange={handleSlideChange} > {slides.map((slide, index) => { return ( <SwiperSlide key={index}> <SetSlide slide={slide} /> </SwiperSlide> ) })} </Swiper> ) } return ( <> <Carousel /> {/* 展示当前活动视频标题 */} <div className="text-center text-cream text-xl mt-2">当前播放:{activeTitle}</div> <div className='flex flex-row justify-around text-cream mt-4 text-lg'> <button className='carousel-button-prev'>prev</button> <div className='text-center carousel-pagination font-italic'></div> <button className='carousel-button-next'>next</button> </div> </> ) } export default CaseStudies_TikTok
可选优化:如果需要切换回之前看过的幻灯片时自动从上次暂停位置继续播放,现有逻辑已经天然支持,因为pause()不会重置视频播放进度;如果需要每次切回都从头播放,在暂停逻辑后加
video.currentTime = 0即可。
内容的提问来源于stack exchange,提问作者JordyJordyJordyJordan
相关产品推荐
相关产品推荐

