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

GSAP ScrollTrigger水平滚动固定时机调整问题求助

解决方案

1. 核心调整思路

  • 让最后一个.gsap-room可以扩展至全屏宽度
  • 修正水平滚动的动画目标(从单个房间改为父容器),精准计算滚动结束位置,确保最后一个房间完全显示时,第二个房间仍保留部分可见区域,同时取消.room-tp的固定状态

2. 修改后的完整代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>GSAP Horizontal Scroll</title>
  <style>
    * {
      box-sizing: border-box;
    }
    body {
      font-family: "FP-ヒラギノ角ゴ ProN W3", sans-serif;
      font-style: normal;
      font-weight: 300;
      width: 100%;
      height: 100%;
      background: #000;
      color: #fff;
      font-size: 13px;
      letter-spacing: 0.05em;
      line-height: 2.5;
      word-wrap: break-word;
      line-break: strict;
    }

    #wrapper {
      position: relative;
      width: 100%;
      min-height: 100%;
      margin: 0;
      overflow: hidden;
    }

    .main {
      display: block;
      padding-top: 0;
    }

    .block {
      width: 100%;
      height: 100vh;
      background: green;
    }
    .room-tp {
      background: pink;
      height: 100vh;
      position: relative;
      overflow: hidden;
      width: 100%;
    }

    .room-tp .top-title {
      padding-top: 65px;
      font-size: 90px;
      text-align: right;
    }

    .room-tp__flex {
      display: flex;
      width: max-content;
    }

    .room-top__img {
      width: 80vw;
      height: calc(100vh - 160px);
    }

    .room-top__img img {
      object-fit: cover;
      width: 100%;
      height: 100%;
    }

    .room-tp__container {
      display: block;
      position: relative;
    }

    .big-space {
      width: 100%;
      height: 100vh;
      background-color: red;
      text-align: center;
      font-size: 30px;
    }

    .blue {
      background-color: teal;
    }

    .gsap-about-flex {
      display: flex;
      width: 100%;
      height: 100vh;
      background-image: url("https://picsum.photos/200");
      background-position: center;
      background-size: cover;
    }

    .gsap-container {
      position: relative;
      height: 100vh;
    }

    .text-container {
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      text-align: center;
    }

    .text-container h2, .text-container p {
      color: white;
      mix-blend-mode: difference;
    }

    .gsap-about-before {
      width: 50%;
      height: 100vh;
      background-color: white;
    }

    .gsap-about-after {
      width: 50%;
      height: 100vh;
      background-color: white;
    }

    /* 新增:让最后一个房间扩展至全屏 */
    .gsap-room:last-child {
      width: 100vw;
    }
    .gsap-room:last-child .room-top__img {
      width: 100%;
    }

  </style>
</head>
<body>
  <div id="wrapper">
    <main class="main">
      <div class="block"></div>

      <div class="gsap-container">
        <div class="gsap-about-flex">
          <div class="gsap-about-before"></div>
          <div class="gsap-about-after"></div>
        </div>
        <div class="text-container">
          <h2>Hello</h2>
          <p>this is some text</p>
        </div>
      </div>

      <section class="room-tp">
        <h2 class="top-title top-title--right">ROOM</h2>

        <div class="room-tp__wrapper">
          <div class="room-tp__flex">
            <div class="gsap-room">
              <a href="/room/#room401" class="room-tp__container">
                <div class="room-top__img">
                  <img src="https://picsum.photos/id/19/200/300" alt="">
                </div>
                <div class="room-top__info">
                  <p class="room-top__list">meeting</p>
                  <p class="room-top__info-title">401</p>
                  <a href="/room/#room401" class="room-top__button">VIEW MORE <i class="ico-arrow"></i></a>
                </div>
              </a>
            </div>
            <div class="gsap-room">
              <a href="/room/#room402" class="room-tp__container">
                <div class="room-top__img">
                  <img src="https://picsum.photos/id/20/200/300" alt="">
                </div>
                <div class="room-top__info">
                  <p class="room-top__list">meeting</p>
                  <p class="room-top__info-title">¥402</p>
                  <a href="/room/#room402" class="room-top__button">VIEW MORE <i class="ico-arrow"></i></a>
                </div>
              </a>
            </div>
            <div class="gsap-room">
              <a href="/room/#room501" class="room-tp__container">
                <div class="room-top__img">
                  <img src="https://picsum.photos/id/21/200/300" alt="">
                </div>
                <div class="room-top__info">
                  <p class="room-top__list">offline</p>
                  <p class="room-top__info-title">501</p>
                  <a href="/room/#room501" class="room-top__button">VIEW MORE <i class="ico-arrow"></i></a>
                </div>
              </a>
            </div>
          </div>
        </div>
      </section>
      <div class="block"></div>
    </main>
  </div>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.7.1/gsap.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.7.1/ScrollTrigger.min.js"></script>
  <script>
    gsap.registerPlugin(ScrollTrigger);

    gsap.to(".gsap-about-before", {
      scrollTrigger: {
        trigger: ".gsap-container",
        start: "top top",
        end: "+=100%",
        scrub: true,
        pin: true,
        toggleActions: "play none none reverse"
      },
      x: '-100%',
      duration: 3
    });

    gsap.to(".gsap-about-after", {
      scrollTrigger: {
        trigger: ".gsap-container",
        start: "top top",
        end: "+=100%",
        scrub: true,
        pin: false,
        toggleActions: "play none none reverse"
      },
      x: '100%',
      duration: 3
    });

    // 修改后的水平滚动逻辑
    const flexContainer = document.querySelector(".room-tp__flex");
    const rooms = gsap.utils.toArray(".gsap-room");
    const roomWidth = rooms[0].offsetWidth;
    // 调整第二个房间的可见宽度,这里设置为20vw(可根据需求修改)
    const visibleSecondRoomWidth = window.innerWidth * 0.2;

    // 计算需要滚动的距离:第一个房间宽度 + (第二个房间宽度 - 保留的可见宽度)
    const scrollDistance = roomWidth + (roomWidth - visibleSecondRoomWidth);

    gsap.to(flexContainer, {
      x: -scrollDistance,
      ease: "none",
      scrollTrigger: {
        trigger: ".room-tp",
        pin: true,
        scrub: true,
        end: () => `+=${scrollDistance}`,
        markers: true,
      }
    });
  </script>
</body>
</html>

3. 关键修改说明

  • CSS调整:给最后一个.gsap-room设置width:100vw,让它铺满全屏,同时同步调整内部图片宽度,确保视觉一致性。
  • 动画目标修正:将水平滚动动画从单个房间元素改为.room-tp__flex容器,避免单个元素偏移导致的计算混乱,符合容器级滚动的逻辑。
  • 结束条件精准计算:通过scrollDistance计算滚动总距离,确保最后一个房间完全显示时,第二个房间仍保留20vw的可见区域(可根据需求修改比例),此时触发ScrollTrigger结束状态,取消.room-tp的固定。
  • 响应式适配:使用window.innerWidth * 0.2计算可见宽度,确保在不同屏幕尺寸下效果一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 19:39:53