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

视差场景下滚动触发div垂直轮播滑动动画实现方法

视差容器垂直滚动轮播实现方案

原有代码问题梳理

  • 滚动方向判断失效:lastScrollTop 变量定义在scroll事件回调内部,每次滚动触发都会被重置为0,完全无法识别向上/向下滚动行为
  • 动画被强制中断:给.div1添加动画类后立刻执行hide(),元素直接被隐藏,滑动动画没有执行机会
  • 缺少反向交互动画:向上回滚时.div2没有对应离场动画,直接硬切显示.div1,不符合轮播的平滑过渡要求
  • 动画参数不合理:9秒的动画时长远超出滚动交互的即时反馈阈值,且子元素未做堆叠定位,切换时会出现布局错位
  • 无重复触发防护:scroll事件触发频率极高,没有加动画状态锁,会导致动画类重复添加、状态混乱

修正后完整代码

CSS 部分

body {
  height: 200vh;
  margin: 0;
}
/* 视差容器做定位基准 */
.scrollTest {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100vh;
  overflow: hidden;
}
/* 两个内容层绝对定位堆叠在同一位置 */
.div1, .div2 {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}
.div2 {
  display: none;
}
/* 向上滑出离场动画 */
.slide-up-out {
  animation: slideUp 0.5s ease forwards;
}
@keyframes slideUp {
  from {
    transform: translateY(0);
    opacity: 1;
  }
  to {
    transform: translateY(-100%);
    opacity: 0;
  }
}
/* 向下滑出离场动画 */
.slide-down-out {
  animation: slideDown 0.5s ease forwards;
}
@keyframes slideDown {
  from {
    transform: translateY(0);
    opacity: 1;
  }
  to {
    transform: translateY(100%);
    opacity: 0;
  }
}

JS 部分

// 把状态变量提到事件外部,持久化存储
let lastScrollTop = 0;
let isAnimating = false; // 动画锁,执行中不响应新触发
const triggerThreshold = 100;
const $scrollTest = $("#scrollTest");
const $div1 = $(".div1");
const $div2 = $(".div2");

window.addEventListener("scroll", function() {
  // 动画执行中直接返回,避免冲突
  if (isAnimating) return;

  const currentScroll = window.scrollY;
  const triggerPoint = $scrollTest.offset().top + triggerThreshold;
  const scrollDirection = currentScroll > lastScrollTop ? 'down' : 'up';

  // 向下滚动超过阈值,且当前显示div1时,触发div1上滑离场
  if (currentScroll > triggerPoint && $div1.is(':visible') && scrollDirection === 'down') {
    isAnimating = true;
    $div1.addClass("slide-up-out");
    // 等动画执行完成再切换显示状态
    $div1.one('animationend', function() {
      $div1.hide().removeClass("slide-up-out");
      $div2.show();
      isAnimating = false;
    })
  }

  // 向上滚动低于阈值,且当前显示div2时,触发div2下滑离场
  if (currentScroll <= triggerPoint && $div2.is(':visible') && scrollDirection === 'up') {
    isAnimating = true;
    $div2.addClass("slide-down-out");
    // 等动画执行完成再切换显示状态
    $div2.one('animationend', function() {
      $div2.hide().removeClass("slide-down-out");
      $div1.show();
      isAnimating = false;
    })
  }

  // 更新上次滚动位置,处理滚动到顶部的边界情况
  lastScrollTop = currentScroll <= 0 ? 0 : currentScroll;
});

HTML 部分

<head>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
</head>
<body>
  <div class="scrollTest" id="scrollTest">
    <div class="div1">
      <img src="https://i.pinimg.com/736x/f7/eb/d8/f7ebd86ff10d7d738d975f227a591600.jpg" width="50%" />
    </div>
    <div class="div2">
      <img src="https://i.pinimg.com/736x/85/60/5a/85605a84fe1acc6e16ff5a84255b41ab.jpg" width="50%" />
    </div>
  </div>
</body>

实现逻辑说明

  • 用transform实现滑动动画比top属性性能更好,不会触发重排,动画流畅度更高
  • 动画锁isAnimating保证同一时间只有一个动画在执行,避免快速滚动时状态错乱
  • 通过animationend事件监听动画完成时机,再切换元素显示状态,保证动画完整播放
  • 滚动方向通过对比当前滚动值和上次存储的滚动值判断,逻辑准确
  • 两个内容层用绝对定位堆叠,切换时不会出现页面布局跳动
  • 容器添加overflow: hidden,滑出容器的内容会被隐藏,完全匹配垂直轮播的视觉效果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 21:09:34