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

如何将绿色Div置于红色Div下方并修复ScrollMagic固定定位失效问题

解决自定义平滑滚动与ScrollMagic.setPin冲突的问题

我完全懂你遇到的麻烦——启用基于transform的自定义平滑滚动后,ScrollMagic的setPin直接失效了。核心原因是ScrollMagic默认依赖原生滚动事件和页面scrollTop值来计算元素位置,但你的平滑滚动是通过修改容器的y偏移模拟出来的,原生scrollTop根本没同步变化,导致ScrollMagic完全摸不准固定元素该待在哪。

下面是完整的修复方案,同时满足红色div固定、绿蓝div在下方、全响应式的所有需求:

核心修复思路

  • 让ScrollMagic改用你自定义的滚动值(也就是scroller.y)来计算动画和固定状态
  • 调整DOM结构和样式,确保元素层级、定位逻辑正确
  • 保持平滑滚动的同时,实时同步滚动数据给ScrollMagic控制器

修改后的完整代码

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Test Code</title>
<!-- 引入必要的依赖库 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.20.2/TweenMax.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ScrollMagic/2.0.8/ScrollMagic.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ScrollMagic/2.0.8/plugins/animation.gsap.min.js"></script>
</head>
<style>
/* 全屏固定视图容器,作为滚动的视口 */
.viewport { 
  overflow: hidden; 
  position: fixed; 
  height: 100vh; 
  width: 100vw; 
  top: 0; 
  left: 0;
  margin: 0;
}
/* 滚动容器:平滑滚动的载体,元素自然垂直排列 */
.scroll-container { 
  position: absolute; 
  width: 100%;
}
/* 红色div:由ScrollMagic负责固定 */
.div1 { 
  width: 70%; 
  height: 70vh; 
  border: 5px solid red; 
  margin: 0 auto;
}
/* 绿蓝div:正常滚动的内容元素 */
.div2 { 
  width: 70%; 
  height: 70vh; 
  border: 5px solid green; 
  margin: 0 auto;
}
.div3 { 
  width: 70%; 
  height: 70vh; 
  border: 5px solid blue; 
  margin: 0 auto;
}
/* 清除默认边距,确保响应式布局正常 */
body {
  margin: 0;
}
</style>
<body>
<div class="viewport">
  <div id="scroll-container">
    <div class="div1"></div>
    <div class="div2"></div>
    <div class="div3"></div>
  </div>
</div>
</body>
<script>
var html = document.documentElement;
var body = document.body;
var scroller = {
  target: document.querySelector("#scroll-container"),
  ease: 0.05, // 平滑滚动速度
  endY: 0,
  y: 0,
  resizeRequest: 1,
  scrollRequest: 0,
};
var requestId = null;

// 初始化ScrollMagic控制器,关键配置自定义滚动容器
var controller = new ScrollMagic.Controller({
  container: scroller.target, // 告诉ScrollMagic监听我们的滚动容器
  scrollTo: function(newPos) {
    window.scrollTo(0, newPos);
  }
});

// 创建Pin场景:让红色div在滚动到绿色div之前保持固定
new ScrollMagic.Scene({
  triggerElement: ".div2", // 触发点为绿色div顶部
  triggerHook: 0,
  duration: "100%" // 固定状态持续到绿色div开始进入视口
})
.setPin(".div1") // 固定红色div
.addTo(controller);

TweenLite.set(scroller.target, { rotation: 0.01, force3D: true });

window.addEventListener("load", onLoad);

function onLoad() {
  updateScroller();
  window.focus();
  window.addEventListener("resize", onResize);
  document.addEventListener("scroll", onScroll);
}

function updateScroller() {
  var resized = scroller.resizeRequest > 0;
  if (resized) {
    var height = scroller.target.clientHeight;
    body.style.height = height + "px";
    scroller.resizeRequest = 0;
    controller.update(); // 窗口 resize 时同步更新ScrollMagic
  }

  var scrollY = window.pageYOffset || html.scrollTop || body.scrollTop || 0;
  scroller.endY = scrollY;
  scroller.y += (scrollY - scroller.y) * scroller.ease;

  if (Math.abs(scrollY - scroller.y) < 0.05 || resized) {
    scroller.y = scrollY;
    scroller.scrollRequest = 0;
  }

  TweenLite.set(scroller.target, { y: -scroller.y });
  
  // 关键:把自定义滚动值同步给ScrollMagic,让它能正确计算固定状态
  controller.scrollTo(scroller.y);
  
  requestId = scroller.scrollRequest > 0 ? requestAnimationFrame(updateScroller) : null;
}

function onScroll() {
  scroller.scrollRequest++;
  if (!requestId) {
    requestId = requestAnimationFrame(updateScroller);
  }
}

function onResize() {
  scroller.resizeRequest++;
  if (!requestId) {
    requestId = requestAnimationFrame(updateScroller);
  }
}
</script>
</html>

关键改动细节

  1. DOM结构调整:把红色div移入scroll-container,让ScrollMagic能正确识别它和绿蓝div的位置关系,自然实现上下排列
  2. 样式优化:移除红色div的position: fixed(交给ScrollMagic的setPin处理),用margin: 0 auto实现水平居中,确保全屏幕响应式
  3. ScrollMagic核心配置:
    • 初始化时指定container: scroller.target,让它监听我们的自定义滚动容器
    • 在updateScroller函数中添加controller.scrollTo(scroller.y),实时同步滚动数据
  4. Pin场景设置:以绿色div为触发点,让红色div在滚动到绿色div顶部时结束固定,完美匹配你的需求

这样修改后,红色div会在滚动到绿色div之前保持固定,绿蓝div正常在下方滚动,平滑滚动效果也完全保留,所有元素都能适配不同屏幕尺寸。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 07:49:06