Sử dụng ScrollSmoother thay thế Locomotive Scroll hay Lenis. (ok)

Dưới đây là example đầy đủ sử dụng:

GSAP ScrollTriggerGSAP ScrollSmoother (smooth scrolling) ✅ gsap.utils.toArray loop nhiều counter ✅ Hàm CounterUpAnimation của bạn


⚠️ 1. Lưu ý

  • ScrollSmoother chỉ có trong GSAP Club Membership. CDN demo sẽ hoạt động nhưng production cần license.

  • Đảm bảo load ScrollSmoother script đúng version.


2. Example HTML + JS

htmlCopyEdit<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Counter with ScrollSmoother</title>
  <style>
    body {
      background: #111;
      color: white;
      font-size: 40px;
      font-family: sans-serif;
      margin: 0;
      padding: 0;
    }
    .smooth-wrapper {
      overflow: hidden;
    }
    .smooth-content {
      will-change: transform;
    }
    .section {
      padding: 150px 0;
      text-align: center;
    }
    .counter {
      font-size: 60px;
    }
  </style>
</head>
<body>

  <div class="smooth-wrapper">
    <div class="smooth-content">

      <div class="section">
        <div class="counter" data-target="100">0+</div>
      </div>

      <div class="section">
        <div class="counter" data-target="200">0+</div>
      </div>

      <div class="section">
        <div class="counter" data-target="300">0+</div>
      </div>

    </div>
  </div>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/ScrollTrigger.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/ScrollSmoother.min.js"></script>

  <script>
    gsap.registerPlugin(ScrollTrigger, ScrollSmoother);

    // Khởi tạo ScrollSmoother
    ScrollSmoother.create({
      wrapper: ".smooth-wrapper",
      content: ".smooth-content",
      smooth: 1.2, // độ mượt
      effects: true
    });

    const CounterUpAnimation = (number, start, end, duration) => {
      let startTimestamp = null;
      const step = (timestamp) => {
        if (!startTimestamp) {
          startTimestamp = timestamp;
        }
        let progress = Math.min((timestamp - startTimestamp) / duration, 1);
        number.innerHTML = Math.floor(progress * (end - start) + start) + '+';
        if (progress < 1) {
          window.requestAnimationFrame(step);
        }
      };
      window.requestAnimationFrame(step);
    };

    // Loop qua tất cả counter
    gsap.utils.toArray(".counter").forEach(counter => {
      let target = parseInt(counter.getAttribute("data-target"));

      ScrollTrigger.create({
        trigger: counter,
        start: "top 80%",
        onEnter: () => {
          CounterUpAnimation(counter, 0, target, 2000);
        },
        once: true,
        markers: true // remove nếu không cần debug
      });
    });
  </script>

</body>
</html>

🔧 3. Giải thích

ScrollSmoother.create khởi tạo smooth scroll. ✅ .smooth-wrapper bọc ngoài .smooth-content đúng chuẩn ScrollSmoother. ✅ ScrollTrigger.create vẫn hoạt động bình thường với ScrollSmoother vì plugin đã tích hợp. ✅ once: true để counter chỉ chạy 1 lần khi scroll tới.


🚀 4. Mở rộng

Nếu muốn:

✅ Dùng GSAP tween thay vì requestAnimationFrame cho counter ✅ Animate opacity + scale counter cùng lúc ✅ Kết hợp SplitText + ScrollSmoother + Counter animation hero

Hãy cho tôi biết, tôi sẽ viết version advanced cho landing page animation của bạn trong hôm nay.

Lỗi ScrollSmoother is not defined nghĩa là bạn chưa có file ScrollSmoother hoặc link CDN bạn đang dùng không có plugin này.

📌 Quan trọng

  • ScrollSmoother là plugin Club GSAP, KHÔNG có trong bản gsap public trên CDN như gsap.min.js hay ScrollTrigger.min.js.

  • Nếu bạn chỉ dùng:

    htmlCopyEdit<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/ScrollTrigger.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/ScrollSmoother.min.js"></script>

    ScrollSmoother.min.js không tồn tại trên CDN public!

Cách dùng đúng

1️⃣ Dùng link CDN chính thức từ GSAP

  • Vào: https://greensock.com/scrollsmoother/

  • Hoặc nếu bạn có tài khoản GSAP Club, tải file .zip về hoặc dùng link CodePen https://assets.codepen.io/16327/ScrollSmoother.min.js.

Ví dụ:

htmlCopyEdit<script src="https://assets.codepen.io/16327/ScrollSmoother.min.js"></script>

svg1g.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Counter with ScrollSmoother</title>
  <style>
    body {
      background: #111;
      color: white;
      font-size: 40px;
      font-family: sans-serif;
      margin: 0;
      padding: 0;
    }
    .smooth-wrapper {
      overflow: hidden;
    }
    .smooth-content {
      will-change: transform;
    }
    .section {
      padding: 150px 0;
      text-align: center;
    }
    .counter {
      font-size: 60px;
    }
  </style>
</head>
<body>

  <div class="smooth-wrapper">
    <div class="smooth-content">

      <div class="section">
        <div class="counter" data-target="100">0+</div>
      </div>

      <div class="section">
        <div class="counter" data-target="200">0+</div>
      </div>

      <div class="section">
        <div class="counter" data-target="300">0+</div>
      </div>

    </div>
  </div>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/ScrollTrigger.min.js"></script>
  <script src="https://assets.codepen.io/16327/ScrollSmoother.min.js"></script>

  <script>
    gsap.registerPlugin(ScrollTrigger, ScrollSmoother);

    // Khởi tạo ScrollSmoother
    ScrollSmoother.create({
      wrapper: ".smooth-wrapper",
      content: ".smooth-content",
      smooth: 1.2, // độ mượt
      effects: true
    });

    const CounterUpAnimation = (number, start, end, duration) => {
      let startTimestamp = null;
      const step = (timestamp) => {
        if (!startTimestamp) {
          startTimestamp = timestamp;
        }
        let progress = Math.min((timestamp - startTimestamp) / duration, 1);
        number.innerHTML = Math.floor(progress * (end - start) + start) + '+';
        if (progress < 1) {
          window.requestAnimationFrame(step);
        }
      };
      window.requestAnimationFrame(step);
    };

    // Loop qua tất cả counter
    gsap.utils.toArray(".counter").forEach(counter => {
      let target = parseInt(counter.getAttribute("data-target"));

      ScrollTrigger.create({
        trigger: counter,
        start: "top 80%",
        onEnter: () => {
          CounterUpAnimation(counter, 0, target, 2000);
        },
        once: true,
        markers: true // remove nếu không cần debug
      });
    });
  </script>

</body>
</html>

Last updated