实现一个百叶窗轮播图

526 阅读3分钟

说在前面

轮播图大家应该都不陌生了吧,常规的轮播图看多了难免会失去新鲜感,今天我们就一起来实现一个不一样的轮播图效果。

在线体验

码上掘金

codePen

codepen.io/yongtaozhen…

代码实现

html容器创建

<div class="container" id="swiper-container"></div>
<div class="carousel-indicators" id="carousel-indicators"></div>

html 我们只需要准备两个 div 容器,一个是图片容器,一个是指示器容器,容器内的具体内容我们在 js 中根据配置信息来动态生成。

css基础布局

:root {
  --hover-width: 30%;
  --container-width: 100%;
  --picture-height: 600px;
}

.container {
  display: flex;
  width: var(--container-width);
  padding: 0 3rem;
  margin: 0 auto;
  overflow: auto;
  justify-content: center;
}

.card {
  flex: 1 1 1%; /* 关键:所有卡片初始平均分配空间 */
  position: relative;
  transition: flex 600ms cubic-bezier(0.25, 1, 0.5, 1); /* 平滑伸缩过渡 */
  cursor: pointer;
  overflow: hidden;
}

.card.is-active {
  flex-basis: 30%; /* 激活卡片占据更大空间 */
}

通过 CSS 变量统一管理关键尺寸,方便后续维护和调整。flex 布局是实现百叶窗效果的核心,flex: 1 1 1% 让所有卡片初始时平均分配空间,而 .is-active 类通过 flex-basis: 30% 让激活卡片展开到指定宽度。

图片配置

const images = [
  {
    src: "https://p2.itc.cn/images01/20210723/f341950b3adb4e9caab343c41d5bd6a4.jpeg", 
    alt: "《千与千寻》",
  },
  {
    src: "https://pic3.zhimg.com/v2-f1159536dc58af663e3955e774a7a13a_r.jpg",
    alt: "《龙猫》",
  },
  …………
];

轮播图展示的图片列表在 js 中配置,方便图片修改和增删。

轮播图配置

const carouselConfig = {
  enabled: true, // 是否启用自动轮播
  interval: 5000, // 轮播间隔时间(毫秒)
  pauseOnHover: true, // 鼠标悬停时暂停轮播
};

错落布局的实现

function calcMarginTop(index) {
  const list = [0, "2.5%", "5%", "2.5%"];
  return list[index % 4];
}

// 生成卡片时应用顶部间距
images.forEach((image, index) => {
  // ...
  card.style.marginTop = calcMarginTop(index);
  // ...
});

通过简单的取余运算,让卡片顶部间距按照 [0, 2.5%, 5%, 2.5%] 的规律循环,形成自然错落的视觉效果,避免了整齐排列的呆板感。

轮播图切换逻辑

// 切换到指定幻灯片
function goToSlide(index) {
  if (index === currentSlide) return;

  const cards = document.querySelectorAll(".card");
  const indicators = document.querySelectorAll(".carousel-indicator");

  // 更新当前幻灯片索引
  currentSlide = index;

  // 更新卡片状态
  cards.forEach((card, i) => {
    if (i === index) {
      card.classList.add("is-active");
    } else {
      card.classList.remove("is-active");
    }
  });

  // 更新指示器状态
  indicators.forEach((indicator, i) => {
    if (i === index) {
      indicator.classList.add("active");
    } else {
      indicator.classList.remove("active");
    }
  });
}

通过 添加/移除 is-active 类控制卡片状态,同时同步更新指示器的激活状态。

自动轮播及交互控制

// 启动自动轮播
function startCarousel() {
  if (!carouselConfig.enabled || isPaused) return;

  clearInterval(carouselInterval);
  carouselInterval = setInterval(() => {
    goToSlide((currentSlide + 1) % images.length);
  }, carouselConfig.interval);
}

// 鼠标进入卡片时暂停并切换
document.addEventListener(
  "mouseenter",
  (event) => {
    const card = event.target.closest(".card");
    if (card) {
      if (carouselConfig.pauseOnHover) {
        pauseCarousel();
      }
      const index = parseInt(card.dataset.index);
      goToSlide(index);
    }
  },
  true
);

自动轮播通过 setInterval 实现,同时支持鼠标悬停暂停功能。卡片的点击 / 悬停交互 通过事件委托方式处理,既提高了性能,又简化了代码。

源码

gitee

gitee.com/zheng_yongt…

github

github.com/yongtaozhen…


  • 🌟 觉得有帮助的可以点个 star~
  • 🖊 有什么问题或错误可以指出,欢迎 pr~
  • 📬 有什么想要实现的功能或想法可以联系我~

公众号

关注公众号『 前端也能这么有趣 』,获取更多有趣内容。

发送 加群 还可以加入群聊,一起来学习(摸鱼)吧~

说在后面

🎉 这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球 🏸 ,平时也喜欢写些东西,既为自己记录 📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解 🙇,写错的地方望指出,定会认真改进 😊,偶尔也会在自己的公众号『前端也能这么有趣』发一些比较有趣的文章,有兴趣的也可以关注下。在此谢谢大家的支持,我们下文再见 🙌。