Tasarımcılar ve geliştiriciler için pratik tavsiyeler ve araçlar

Tasarım görüşleri ve kaynaklar

Venue related image

GSAP

Burada tüm GSAP sınıflarına, GSAP'a bağlı Webflow değişkenlerine ve GSAP'ı nasıl devre dışı bırakacağınıza dair talimatlara erişebilirsiniz. Bu, bu şablonu tamamen kişiselleştirmenize ve önemli ölçüde değiştirmenize olanak tanır.

Genel Bakış

Bu şablon, akıcı ve etkileşimli animasyonlar oluşturmak için GSAP (GreenSock Animation Platform) ve ScrollTrigger kullanır. Ek kütüphaneler arasında metin animasyonları için SplitType bulunur. Bu kurulumla şunları yapabilirsiniz:

  • Hover'da düğme ve metni animasyonla göster
  • Kaydırmada başlıkları göster
  • Görselleri bulanıklık efektiyle animasyonla göster
  • Fare izleri ve geri sayım sayaçları oluşturun

Düğme hover animasyonu

  // ===== UPDATED BUTTON HOVER ANIMATION =====
    document.querySelectorAll(".button-wrapper,.dropdown-nav-link").forEach(button => {
      const text1 = button.querySelector(".btn-text-1,.nav-link-text-1");
      const text2 = button.querySelector(".btn-text-2,.nav-link-text-2");
      if (!text1 || !text2) return;

      // Split text into individual spans
      function splitText(textEl) {
        const text = textEl.textContent.trim();
        if (!text) return;
        textEl.innerHTML = '';
        text.split('').forEach(letter => {
          const span = document.createElement('span');
          if (letter === ' ') {
            span.innerHTML = ' ';
            span.style.display = 'inline-block';
            span.style.width = '0.3em';
          } else {
            span.textContent = letter;
            span.style.display = 'inline-block';
          }
          textEl.appendChild(span);
        });
        textEl.style.position = 'relative';
      }

      splitText(text1);
      splitText(text2);

      const spans1 = text1.querySelectorAll('span');
      const spans2 = text2.querySelectorAll('span');
      const baseStagger = 0.04;

      // set initial state for text2
      gsap.set(spans2, { y: 40, opacity: 0 });

      const tl = gsap.timeline({ paused: true });

      // animate text1 up and out
      tl.to(spans1, {
        y: -45,
        opacity: 0,
        stagger: baseStagger,
        duration: 0.20, // shorter duration
        ease: "power2.in"
      }, 0.001);

      // animate text2 from below into place
      tl.to(spans2, {
        y: -26,
        opacity: 1,
        stagger: baseStagger,
        duration: 0.20, // shorter duratio
        ease: "power2.out"
      }, 0.001);

      // hover triggers
      button.addEventListener("mouseenter", () => tl.play());
      button.addEventListener("mouseleave", () => tl.reverse());
    });

Düğmelerin (.button-wrapper ve .dropdown-nav-link) iki metin katmanı vardır:

  • .btn-text-1 / .nav-link-text-1 → initial text
  • .btn-text-2 / .nav-link-text-2 → text on hover
Kişiselleştirme:
  • Animasyon hızını veya stilini ayarlamak için GSAP zaman çizelgesindeki y, opacity, duration veya stagger değerlerini değiştirin.

Görsel kaydırma animasyonları

// ===== IMAGE SCROLL ANIMATION =====
    gsap.utils.toArray(".blur-image-animation").forEach((img) => {
      gsap.fromTo(img,
        {
          filter: "blur(10px)",
          scale: 1.1,
          opacity: 0,
        },
        {
          scrollTrigger: {
            trigger: img,
            start: "top 80%",
            toggleActions: "play none none none",
            once: true
          },
          filter: "blur(0px)",
          scale: 1,
          opacity: 1,
          duration: 1.2,
          ease: "power2.out"
        }
      );
    });
  });
  • '.blur-image-animation' sınıfına sahip görseller, kullanıcı kaydırdıkça bulanık ve yakınlaştırılmış halden net ve tam görünür hale geçerek akıcı bir şekilde ortaya çıkar.
  • Yalnızca 768px'den geniş ekranlarda tetiklenir.
  • .blur-image-animation → Kaydırmada animasyonlu göstermek istediğiniz herhangi bir görsel.
Kişiselleştirme:
  • Görselin kaydırma sırasında ne zaman animasyona başlayacağını kontrol etmek için GSAP zaman çizelgesini düzenleyerek bulanıklık miktarını, yakınlaştırma seviyesini (scale), animasyon hızını (duration), yumuşatma stilini (ease) ve kaydırma tetikleme noktasını (örn. "start: 'top 80%'" ayarını) değiştirebilirsiniz.

Metin ortaya çıkma animasyonu

 // ===== BIG HEADING SCROLL ANIMATION =====
   // Only run heading animation if screen width is above 768px (adjust if needed)
if (window.innerWidth > 768) {
  document.querySelectorAll(".text-reveal-animation").forEach((heading) => {
    const split = new SplitType(heading, { types: 'chars' });
    const chars = split.chars;
    const center = (chars.length - 1) / 2;

    gsap.set(chars, {
      opacity: 0,
      filter: 'blur(10px)',
      scale: 0.8
    });

    gsap.to(chars, {
      opacity: 1,
      filter: 'blur(0px)',
      scale: 1,
      duration: 0.6,
      ease: 'power2.out',
      stagger: (i) => Math.abs(i - center) * 0.04,
      scrollTrigger: {
        trigger: heading,
        start: 'top 90%',
        once: true
      }
    });
  });
}
  • .text-reveal-animation → splits text into characters and animates from blur/scale to clear/normal.
  • Yalnızca 768px'den geniş ekranlarda tetiklenir.
Kişiselleştirme:
  • Farklı efektler oluşturmak için GSAP fromTo içindeki filter, scale, opacity veya duration değerlerini ayarlayın.
  • Animasyonların ne zaman tetikleneceğini kontrol etmek için scrollTrigger.start değerini değiştirin.

Sayaç animasyonu

<script>
    // ===== COUNTER ANIMATION =====
            window.addEventListener("load", function() {
                const counters = document.querySelectorAll("[data-count]");
 
                const observer = new IntersectionObserver( (entries, observer) => {
                    entries.forEach(entry => {
                        if (!entry.isIntersecting)
                            return;
 
                        const el = entry.target;
 
                        // Remove the thousand separator dots, then convert to a number.
                        const target = parseInt(el.getAttribute("data-count").replace(/\./g, ""), 10);
 
                        const duration = 3000;
                        // in ms
                        const frameRate = 60;
                        const totalFrames = Math.round(duration / (1000 / frameRate));
                        let frame = 0;
 
                        const count = () => {
                            frame++;
                            const progress = frame / totalFrames;
                            const current = Math.round(target * progress);
 
                            // Format the number with thousand separators
                            el.innerText = current.toLocaleString("id-ID");
 
                            if (frame < totalFrames) {
                                requestAnimationFrame(count);
                            } else {
                                el.innerText = target.toLocaleString("id-ID");
                            }
                        }
                        ;
 
                        requestAnimationFrame(count);
                        observer.unobserve(el);
                    }
                    );
                }
                ,{
                    threshold: 0.6
                });
 
                counters.forEach(el => observer.observe(el));
            });
        </script>

Bu JavaScript kodu, öğe görünüm alanında görünür olduğunda başlayan akıcı bir sayma animasyonu oluşturur. Genellikle kaydırmada animasyonlu istatistikler veya sayı sayaçları için kullanılır.

Bu betik, data-count özniteliğine sahip HTML öğelerinin içindeki sayısal değerleri animasyonla gösterir. Kullanıcı bu öğeleri içeren bir bölüme kaydırdığında, sayılar 0'dan hedef değerlerine kadar akıcı bir şekilde sayılır.

Geri sayım sayacı

// TIMER JS (GSAP-based)
const newYearEnd = new Tarih('Jan 01 2027 00:00:00');

const time = {
  days: 0,
  hours: 0,
  minutes: 0,
  seconds: 0
};

// Elements
const __days = document.querySelector("#days");
const __hours = document.querySelector("#hours");
const __minutes = document.querySelector("#minutes");
const __seconds = document.querySelector("#seconds");

// Function to calculate remaining time
function getTime() {
  const current = new Tarih();
  const totalSeconds = (newYearEnd - current) / 1000;

  return {
    days: Math.floor(totalSeconds / 3600 / 24),
    hours: Math.floor(totalSeconds / 3600) % 24,
    minutes: Math.floor(totalSeconds / 60) % 60,
    seconds: Math.floor(totalSeconds % 60)
  };
}

// Smoothly animate numbers
gsap.to(time, {
  days: getTime().days,
  hours: getTime().hours,
  minutes: getTime().minutes,
  seconds: getTime().seconds,
  duration: 1,
  repeat: -1,
  ease: "none",
  onUpdate: () => {
    const t = getTime(); // recalc real time on each frame
    __days.innerHTML = t.days < 10 ? `0${t.days}` : t.days;
    __hours.innerHTML = t.hours < 10 ? `0${t.hours}` : t.hours;
    __minutes.innerHTML = t.minutes < 10 ? `0${t.minutes}` : t.minutes;
    __seconds.innerHTML = t.seconds < 10 ? `0${t.seconds}` : t.seconds;
  }
});
  • 1 Ocak 2026 00:00:00'a geri sayım (gerektiğinde güncelleyin).
  • Gün, saat, dakika ve saniyeyi GSAP animasyonuyla gerçek zamanlı günceller.
Kişiselleştirme:
  • Kendi geri sayımınız için newYearEnd tarihini değiştirin.
  • Sayıları Webflow üzerinden #days, #hours, #minutes, #seconds ile biçimlendirin.

Animasyon nasıl devre dışı bırakılır veya kaldırılır

  • GSAP'ı tamamen devre dışı bırakmak için: GSAP kütüphanelerinin hiçbirini yüklemeyebilir veya webflow.Push kod bloğunu kaldırabilirsiniz
  • Gün, saat, dakika ve saniyeyi GSAP animasyonuyla gerçek zamanlı günceller.
GSAP'ı tamamen devre dışı bırakmak için:
Özel kodunuzdaki animasyon betiklerini devre dışı bırakın:

/*
Webflow ||= [];
Webflow.push(() => {
    gsap.registerPlugin(ScrollTrigger);
    // All GSAP animations here are now inactive
});
*/

Sınıfları kaldırarak belirli animasyonları devre dışı bırakın

- Düğme Sarmalayıcı
- Btn Text 1 / Btn Text 2
- Metin Ortaya Çıkma Animasyonu
- Bulanık Görsel Animasyonu