如何实现仿指定网站的Swiper.js滑块背景切换动画
问题描述
我需要实现一个每视图显示3个幻灯片的Swiper.js滑块,滑块带有全屏背景图,切换时背景图随滑块索引同步变化。尝试用Swiper完全复刻目标效果,动画部分采用GSAP实现,但目前仅autoAlpha属性能正常工作,使用scale(0)到scale(1)这类动画时效果混乱。当前用两张示例图按索引切换,但动画效果与目标不符。
核心问题分析
- 使用的Swiper 4.4.2版本过旧,与GSAP 3.x的动画调度逻辑存在冲突
- CSS中给
.activeBG设置了transition属性,与GSAP的动画产生双重过渡,导致scale动画异常 - 背景图未设置默认隐藏状态,非激活背景会干扰视觉效果
slidesPerView设为2.5,不符合“每视图3个幻灯片”的需求- 循环模式下的背景索引匹配逻辑未处理边界情况
修正后的完整代码
HTML
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@9/swiper-bundle.min.css" /> <!-- 滑块区域 --> <div class="projectSlider"> <!-- 背景图,与幻灯片一一对应 --> <img src="https://i.im.ge/2022/12/16/dHOzYJ.windows-FV6Pma5U-98-unsplash.jpg" data-index="0" alt="" class="prjctbg" /> <img src="https://i.im.ge/2022/12/16/dH2dSz.jenny-ueberberg-BaSeK7rwc1A-unsplash.jpg" data-index="1" alt="" class="prjctbg" /> <img src="https://i.im.ge/2022/12/16/dHOzYJ.windows-FV6Pma5U-98-unsplash.jpg" data-index="2" alt="" class="prjctbg" /> <img src="https://i.im.ge/2022/12/16/dH2dSz.jenny-ueberberg-BaSeK7rwc1A-unsplash.jpg" data-index="3" alt="" class="prjctbg" /> <img src="https://i.im.ge/2022/12/16/dHOzYJ.windows-FV6Pma5U-98-unsplash.jpg" data-index="4" alt="" class="prjctbg" /> <img src="https://i.im.ge/2022/12/16/dH2dSz.jenny-ueberberg-BaSeK7rwc1A-unsplash.jpg" data-index="5" alt="" class="prjctbg" /> <div class="swiper-container"> <div class="swiper-wrapper"> <div class="swiper-slide"> <div class="swiper-slide-container"> <a href="#" class="details"> <h1 class="elmt">Audiovisual <br />Design</h1> <p class="elmt"><span>Video Installation</span></p> </a> </div> </div> <div class="swiper-slide"> <div class="swiper-slide-container"> <a href="#" class="details"> <h1 class="elmt">Exhibition <br />Design</h1> <p class="elmt"><span>Multimedia Exhibition</span></p> </a> </div> </div> <div class="swiper-slide"> <div class="swiper-slide-container"> <a href="#" class="details"> <h1 class="elmt">Texts and <br />Images</h1> <p class="elmt"><span>website + Print Magazine</span></p> </a> </div> </div> <div class="swiper-slide"> <div class="swiper-slide-container"> <a href="#" class="details"> <h1 class="elmt">Material and <br />Light</h1> <p class="elmt"><span>Short Video</span></p> </a> </div> </div> <div class="swiper-slide"> <div class="swiper-slide-container"> <a href="./projectDetails.html" class="details"> <h1 class="elmt">Dimension <br />Design</h1> <p class="elmt"><span>Rendered Image</span></p> </a> </div> </div> <div class="swiper-slide"> <div class="swiper-slide-container"> <a href="./projectDetails.html" class="details"> <h1 class="elmt">App <br />Design</h1> <p class="elmt"><span>Sustainability App</span></p> </a> </div> </div> </div> <div class="swiper-pagination"></div> <div class="swiper-button-prev"></div> <div class="swiper-button-next"></div> </div> </div> <script src="https://cdn.jsdelivr.net/npm/swiper@9/swiper-bundle.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.3/gsap.min.js"></script>
CSS
@import url('https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,300;0,400;0,500;0,600;1,200&display=swap'); * { margin: 0; padding: 0; font-family: 'Poppins', sans-serif; box-sizing: border-box; } body a { text-decoration: none; color: #ffffff; } .projectSlider { width: 100vw; height: 100vh; position: relative; overflow: hidden; } /* Swiper组件样式调整 */ .projectSlider .swiper-pagination { bottom: 26px; } .projectSlider .swiper-slide-prev { justify-content: flex-end; } .projectSlider .swiper-slide-next { justify-content: flex-start; } .projectSlider .swiper-button-prev, .projectSlider .swiper-button-next { top: 94%; width: 50px; height: 50px; background-size: contain; background-position: center; } .projectSlider .swiper-button-prev { right: 100px; left: auto; background-image: url("../images/icons/prev.svg"); } .projectSlider .swiper-button-next { right: 35px; left: auto; background-image: url("../images/icons/next.svg"); } /* 背景图样式 */ .projectSlider .prjctbg { position: absolute; width: 100%; height: 100%; object-fit: cover; filter: blur(8px); -webkit-filter: blur(8px); opacity: 0; visibility: hidden; } .projectSlider .prjctbg.activeBG { z-index: 1; } /* Swiper容器与幻灯片样式 */ .swiper-container { position: relative; width: 100%; height: 100%; z-index: 2; } .swiper-slide { height: 100%; display: flex; align-items: center; justify-content: center; transform: scale(0.8); text-align: center; transition: transform 200ms cubic-bezier(0.165, 0.84, 0.44, 1); } .swiper-slide p { overflow: hidden; color: #fff; font-size: 1em; } .swiper-slide p span { transform: translateY(100px); display: block; transition: transform 1000ms cubic-bezier(0.165, 0.84, 0.44, 1) 0.2s; } .swiper-slide h1 { color: #fff; font-size: 3.8em; line-height: 100%; margin: 0 0 30px 0; transform: scale(0.5); font-weight: 600; transition: transform 1000ms cubic-bezier(0.165, 0.84, 0.44, 1) 0.2s; } /* 激活幻灯片样式 */ .swiper-slide-active { transform: scale(1); } .swiper-slide-active p span { transform: translateY(0); } .swiper-slide-active h1 { transform: scale(1); transition-delay: 0.15s; }
JavaScript
const imgs = document.querySelectorAll(".prjctbg"); const swiper = new Swiper(".swiper-container", { pagination: { el: ".swiper-pagination", clickable: true, }, spaceBetween: 10, slidesPerView: 3, // 设置每视图显示3个幻灯片 centeredSlides: true, roundLengths: true, loop: true, loopAdditionalSlides: 6, // 匹配幻灯片数量,避免循环时索引异常 navigation: { nextEl: ".swiper-button-next", prevEl: ".swiper-button-prev", }, on: { // 初始化时显示第一个背景图 init: function() { const initialIndex = this.realIndex; imgs.forEach(img => { if (img.getAttribute("data-index") == initialIndex) { img.classList.add("activeBG"); gsap.set(img, { autoAlpha: 1, scale: 1 }); } else { gsap.set(img, { autoAlpha: 0, scale: 1.2 }); } }); }, // 幻灯片切换开始时执行背景动画 slideChangeTransitionStart: function() { const slideIndex = this.realIndex; // 先隐藏所有背景图 imgs.forEach(img => { if (img.classList.contains("activeBG")) { gsap.to(img, 0.5, { autoAlpha: 0, scale: 1.2 }); img.classList.remove("activeBG"); } }); // 显示当前索引对应的背景图 const activeBg = document.querySelector(`.prjctbg[data-index="${slideIndex}"]`); activeBg.classList.add("activeBG"); gsap.fromTo(activeBg, 1, { autoAlpha: 0, scale: 1.2 }, { autoAlpha: 1, scale: 1, ease: "power2.out" } ); } }, breakpoints: { 768: { slidesPerView: 1, }, }, });
关键修改说明
- 升级Swiper版本:替换为最新稳定版,解决与GSAP的兼容性问题
- 移除CSS过渡冲突:删除
.activeBG的transition属性,由GSAP完全控制动画 - 修正幻灯片数量:设置
slidesPerView: 3,实现每视图3个幻灯片的需求 - 优化背景动画逻辑:
- 初始化时设置所有背景图的初始状态
- 切换时先淡出旧背景,再淡入新背景并执行scale动画
- 修复循环索引问题:调整
loopAdditionalSlides为幻灯片数量,确保循环时索引匹配正确 - 层级管理:给Swiper容器设置
z-index: 2,确保幻灯片内容在背景图上方
内容的提问来源于stack exchange,提问作者NAYMUR
相关产品推荐
相关产品推荐

