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

如何在HTML+CSS+JS图片滑块中实现反向切换动画?

图片滑块反向切换动画修复方案

问题说明

当前实现的图片滑块已支持导航箭头、指示圆点、自动播放,点击元素会重置计时器,正向循环切换正常。但点击「prev」按钮或当前圆点之前的任意圆点时,无法触发反向切换动画,需要实现该场景下滑块从左到右的切换效果。

修复思路

核心是根据切换方向区分动画逻辑:

  • 正向切换(next/当前圆点之后的圆点):保持原有「旧滑块左滑隐藏,新滑块右滑显示」的动画
  • 反向切换(prev/当前圆点之前的圆点):新增「旧滑块右滑隐藏,新滑块左滑显示」的动画

修改后的完整代码

JavaScript 代码

var slider = document.getElementsByClassName("slider")[0];
var sliderDots = Array.prototype.slice.call(document.getElementsByClassName("dots")[0].children);
var sliderContents = Array.prototype.slice.call(document.getElementsByClassName("elements")[0].children);
var sliderArrowLeft = document.getElementsByClassName("arrow-left")[0];
var sliderArrowRight = document.getElementsByClassName("arrow-right")[0];
var sliderSpeed = 4000,
    currentSlide = 0,
    currentActive = 0,
    sliderTimer = 0;

// 新增direction参数,判断切换方向:forward/backward
function playSlide(slide, direction = 'forward') {
  // 清空所有元素的状态类
  for (var k = 0; k < sliderDots.length; k++) {
    sliderContents[k].classList.remove("active", "inactive", "active-reverse", "inactive-reverse");
    sliderDots[k].classList.remove("active");
  }

  // 处理循环边界
  if (slide < 0) {
    slide = currentSlide = sliderContents.length - 1;
  }
  if (slide > sliderContents.length - 1) {
    slide = currentSlide = 0;
  }

  if (currentActive != currentSlide) {
    // 根据方向给旧滑块添加隐藏类
    if (direction === 'forward') {
      sliderContents[currentActive].classList.add("inactive");
    } else {
      sliderContents[currentActive].classList.add("inactive-reverse");
    }
  }

  // 根据方向给新滑块添加显示类
  if (direction === 'forward') {
    sliderContents[slide].classList.add("active");
  } else {
    sliderContents[slide].classList.add("active-reverse");
  }
  
  sliderDots[slide].classList.add("active");
  currentActive = currentSlide;

  // 重置计时器
  clearTimeout(sliderTimer);
  sliderTimer = setTimeout(function() {
    playSlide(currentSlide += 1);
  }, sliderSpeed)
}

// 左箭头点击:反向切换
sliderArrowLeft.addEventListener("click", function() {
  playSlide(currentSlide -= 1, 'backward');
})

// 右箭头点击:正向切换
sliderArrowRight.addEventListener("click", function() {
  playSlide(currentSlide += 1);
})

// 圆点点击:判断点击的圆点是在当前之前还是之后,确定方向
for (var l = 0; l < sliderDots.length; l++) {
  sliderDots[l].addEventListener("click", function() {
    var targetIndex = sliderDots.indexOf(this);
    var direction = targetIndex < currentSlide ? 'backward' : 'forward';
    playSlide(currentSlide = targetIndex, direction);
  })
}

playSlide(currentSlide);

CSS 代码

.slider {
  overflow: hidden;
  position: relative;
}

.contents {
  width: 100%;
  height: 200px;
  position: relative;
  overflow: hidden;
}

.arrow-left,
.arrow-right {
  width: 50px;
  height: 50px;
  bottom: 0;
  cursor: pointer;
  display: block;
  text-align: center;
  line-height: 50px;
  background: rgb(200,200,200);
  position: absolute;
  z-index: 2;
}

.arrow-left {
  left: 0;
}

.arrow-right {
  right: 0;
}

.dots {
  height: 14px;
  bottom: 0;
  left: 50%;
  font-size: 0;
  text-align: right;
  position: absolute;
  z-index: 2;
  transform: translateX(-50%);
}

.dot {
  width: 12px;
  height: 12px;
  margin-left: 5px;
  margin-right: 5px;
  display: inline-block;
  cursor: pointer;
  border-style: solid;
  border-width: 1px;
  border-color: rgb(100, 100, 100);
}

.dot.active {
  background: rgb(200, 200, 200);
}

.elements {
  width: 100%;
  overflow: hidden;
  transform: translate(0px);
}

.image {
  width: 100%;
  height: 100px;
  top: 0;
  position: absolute;
  opacity: 0;
}

.image span {
  width: 100%;
  height: 100px;
  text-align: center;
  line-height: 100px;
  display: block;
  background: rgb(200, 200, 200);
}

/* 正向切换类 */
.image.active {
  position: relative;
  z-index: 1;
  opacity: 1;
}
.image.inactive {
  z-index: -3;
  opacity: 1;
}
.image.active span {
  animation: show .5s ease-in-out forwards;
}
.image.inactive span {
  animation: hide .5s ease-in-out forwards;
}

/* 反向切换类 */
.image.active-reverse {
  position: relative;
  z-index: 1;
  opacity: 1;
}
.image.inactive-reverse {
  z-index: -3;
  opacity: 1;
}
.image.active-reverse span {
  animation: show-reverse .5s ease-in-out forwards;
}
.image.inactive-reverse span {
  animation: hide-reverse .5s ease-in-out forwards;
}

/* 正向动画关键帧 */
@keyframes show {
  0% {
    transform: translateX(+100%);
  }
  100% {
    transform: translateX(0);
  }
}
@keyframes hide {
  0% {
    opacity: 1;
    transform: translateX(0);
  }
  100% {
    opacity: 0;
    transform: translateX(-100%);
  }
}

/* 反向动画关键帧 */
@keyframes show-reverse {
  0% {
    transform: translateX(-100%);
  }
  100% {
    transform: translateX(0);
  }
}
@keyframes hide-reverse {
  0% {
    opacity: 1;
    transform: translateX(0);
  }
  100% {
    opacity: 0;
    transform: translateX(+100%);
  }
}

HTML 代码

<div class="slider">
  <div class="contents">
    <div class="arrow-left">prev</div>
    <div class="arrow-right">next</div>
    <div class="dots">
      <li class="dot"></li>
      <li class="dot"></li>
      <li class="dot"></li>
    </div>
    <div class="elements">
      <div class="image"><span>image 1</span></div>
      <div class="image"><span>image 2</span></div>
      <div class="image"><span>image 3</span></div>
    </div>
  </div>
</div>

关键修改点

  1. JS中给playSlide函数新增direction参数,判断切换是正向还是反向
  2. 圆点点击时,对比目标索引和当前索引,自动判断切换方向
  3. CSS中新增反向切换的类和对应的关键帧动画,实现旧滑块右滑隐藏、新滑块左滑显示的效果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 11:54:58