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

如何实现仿指定网站的Swiper.js滑块背景切换动画

问题描述

我需要实现一个每视图显示3个幻灯片的Swiper.js滑块,滑块带有全屏背景图,切换时背景图随滑块索引同步变化。尝试用Swiper完全复刻目标效果,动画部分采用GSAP实现,但目前仅autoAlpha属性能正常工作,使用scale(0)到scale(1)这类动画时效果混乱。当前用两张示例图按索引切换,但动画效果与目标不符。

核心问题分析
  1. 使用的Swiper 4.4.2版本过旧,与GSAP 3.x的动画调度逻辑存在冲突
  2. CSS中给.activeBG设置了transition属性,与GSAP的动画产生双重过渡,导致scale动画异常
  3. 背景图未设置默认隐藏状态,非激活背景会干扰视觉效果
  4. slidesPerView设为2.5,不符合“每视图3个幻灯片”的需求
  5. 循环模式下的背景索引匹配逻辑未处理边界情况
修正后的完整代码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 10:50:16