Text Animation dengan GSAP: Membuat Animasi Teks yang Dinamis

Pernahkah kamu lihat website yang memiliki teks yang bergerak dengan cara yang cool dan engaging? Mungkin teks yang muncul satu per satu seperti di-ketik, atau teks yang berwarna-warni, atau teks yang bergerak bersamaan dengan scroll? Semua itu bisa dibuat dengan GSAP!

Text animation adalah salah satu cara paling efektif untuk membuat website lebih engaging dan memorable. Teks yang animated tidak hanya menarik perhatian, tapi juga membantu guide user journey dan membuat konten lebih digestible. Di artikel ini, kita akan explore berbagai teknik text animation menggunakan GSAP, dari yang simple seperti fade-in dan slide, hingga yang lebih advanced seperti typewriter effect dan character-by-character animation.

Mari kita mulai!

Kenapa Text Animation Penting?

Sebelum kita dive ke teknik-teknik, penting untuk understand kenapa text animation itu valuable:

1. Attracts Attention

Teks yang animated lebih menarik perhatian daripada teks statis. User's eyes akan tertarik ke elemen yang bergerak, yang perfect untuk highlight important messages atau calls-to-action.

2. Improves Readability

Teks yang muncul secara gradual (bukan semua sekaligus) lebih mudah di-baca dan dipahami oleh user, terutama untuk headlines atau important information.

3. Creates Personality

Animasi teks bisa memberikan personality dan feel kepada brand kamu. Typewriter effect terasa vintage dan friendly, sementara scramble effect terasa techy dan modern.

4. Guides User Journey

Dengan animate teks pada waktu yang tepat (seperti dengan scroll atau click), kamu bisa guide user melalui content journey dengan lebih smooth.

5. Improves Engagement

Website dengan text animations terasa lebih polished dan professional, yang biasanya menghasilkan lebih tinggi engagement dan conversion rates.

Text Animation Technique 1: Fade In

Fade in adalah text animation yang paling simple. Teks akan muncul secara bertahap dari transparan (opacity 0) menjadi fully visible (opacity 1). Buatlah file baru

fadein.html

<!DOCTYPE html>
<html lang="id">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>1. GSAP - Fade In Text</title>
    <style>
        /* CSS Umum untuk semua contoh */
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            margin: 0;
            background-color: #f0f2f5;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            padding: 20px;
        }
        .section {
            background: white;
            padding: 50px;
            border-radius: 20px;
            box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
            text-align: center;
            width: 90%;
            max-width: 700px;
        }
        h2 {
            color: #1a1a2e;
            font-size: 2.5rem; /* Lebih besar */
            margin-bottom: 25px;
        }
        p {
            color: #4a4a4a;
            font-size: 1.5rem; /* Lebih besar */
            font-weight: 500;
            min-height: 50px; /* Ruang agar tidak 'jump' */
            line-height: 1.5;
        }
        button {
            background: #667eea;
            color: white;
            border: none;
            padding: 20px 40px; /* Lebih besar */
            border-radius: 10px;
            font-size: 1.2rem; /* Lebih besar */
            font-weight: bold;
            cursor: pointer;
            margin-top: 30px;
            transition: transform 0.2s ease, background-color 0.2s ease;
        }
        button:hover {
            background: #5a6ecf;
            transform: translateY(-3px);
        }
    </style>
</head>
<body>

    <!-- === KONTEN SPESIFIK UNTUK CONTOH INI === -->
    <div class="section">
        <h2>1. Fade In Text</h2>
        <p class="animated-text" id="fadeText">
            Teks ini akan muncul dari transparan menjadi terlihat.
        </p>
        <button onclick="animateFadeIn()">Jalankan Animasi</button>
    </div>

    <!-- Load GSAP dari CDN -->
    <script src="<https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js>"></script>

    <script>
        // === JAVASCRIPT SPESIFIK UNTUK CONTOH INI ===

        function animateFadeIn() {
            // Menganimasikan elemen dengan ID 'fadeText'
            // 'from' berarti animasi dimulai DARI state yang kita definisikan
            // menuju ke state aslinya di CSS.
            gsap.from("#fadeText", {
                // Mulai dari state:
                opacity: 0,      // Benar-benar transparan

                // Pengaturan Animasi:
                duration: 1.5,   // Berlangsung selama 1.5 detik
                ease: "power2.out", // Membuat gerakan terasa halus di akhir
            });
        }
    </script>

</body>
</html>

Cara Kerjanya:

  • opacity: 0 = mulai dari transparan
  • Animasi akan proceed ke opacity 1 (default di HTML) secara smooth
  • Durasi 1.5 detik dengan easing yang smooth
Animasi Fade In
Animasi Fade In

Text Animation Technique 2: Slide In

Slide in memberikan effect teks bergerak dari satu sisi menuju posisi normal. Perfect untuk judul atau lead text.

slidein.html

<!DOCTYPE html>
<html lang="id">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>2. GSAP - Slide In Text</title>
    <style>
        /* CSS Umum untuk semua contoh (SAMA SEPERTI SEBELUMNYA) */
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            margin: 0;
            background-color: #f0f2f5;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            padding: 20px;
        }
        .section {
            background: white;
            padding: 50px;
            border-radius: 20px;
            box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
            text-align: center;
            width: 90%;
            max-width: 700px;
            overflow: hidden; /* Penting untuk menyembunyikan elemen sebelum masuk */
        }
        h2 {
            color: #1a1a2e;
            font-size: 2.5rem;
            margin-bottom: 25px;
        }
        p {
            color: #4a4a4a;
            font-size: 1.5rem;
            font-weight: 500;
            min-height: 50px;
            line-height: 1.5;
        }
        button {
            background: #667eea;
            color: white;
            border: none;
            padding: 20px 40px;
            border-radius: 10px;
            font-size: 1.2rem;
            font-weight: bold;
            cursor: pointer;
            margin-top: 30px;
            transition: transform 0.2s ease, background-color 0.2s ease;
        }
        button:hover {
            background: #5a6ecf;
            transform: translateY(-3px);
        }
    </style>
</head>
<body>

    <!-- === KONTEN SPESIFIK UNTUK CONTOH INI === -->
    <div class="section">
        <h2>2. Slide In Text</h2>
        <p class="animated-text" id="slideText">
            Teks ini akan meluncur masuk dari sebelah kiri.
        </p>
        <button onclick="animateSlideIn()">Jalankan Animasi</button>
    </div>

    <!-- Load GSAP dari CDN -->
    <script src="<https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js>"></script>

    <script>
        // === JAVASCRIPT SPESIFIK UNTUK CONTOH INI ===

        function animateSlideIn() {
            // Menganimasikan elemen dengan ID 'slideText'
            // 'from' berarti animasi dimulai DARI state yang kita definisikan.
            gsap.from("#slideText", {
                // Mulai dari state:
                x: -200,         // Posisi 200px di sebelah kiri (di luar layar)
                opacity: 0,      // Benar-benar transparan
                
                // Pengaturan Animasi:
                duration: 1.2,   // Berlangsung selama 1.2 detik
                ease: "power4.out", // Gerakan yang sangat halus dan melambat di akhir
            });
        }
    </script>

</body>
</html>

Animasi Slide In
Animasi Slide In

Variasi Slide In:

*// Slide dari kanan*
gsap.from("#slideText", { x: 100, opacity: 0, duration: 1 });

*// Slide dari atas*
gsap.from("#slideText", { y: -100, opacity: 0, duration: 1 });

*// Slide dari bawah*
gsap.from("#slideText", { y: 100, opacity: 0, duration: 1 });

*// Slide dari diagonal*
gsap.from("#slideText", { x: 100, y: -100, opacity: 0, duration: 1 });

Text Animation Technique 3: Typewriter Effect

Typewriter effect adalah animation paling popular untuk teks. Ini membuat teks terlihat seperti sedang di-ketik character-by-character.

Untuk typewriter effect, kita perlu manual split teks jadi character-character individual:

typewriter.html

<!DOCTYPE html>
<html lang="id">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>3. GSAP - Typewriter Effect</title>
    <style>
      /* CSS Umum untuk semua contoh (SAMA SEPERTI SEBELUMNYA) */
      body {
        font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
        margin: 0;
        background-color: #f0f2f5;
        display: flex;
        justify-content: center;
        align-items: center;
        min-height: 100vh;
        padding: 20px;
      }
      .section {
        background: white;
        padding: 50px;
        border-radius: 20px;
        box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
        text-align: center;
        width: 90%;
        max-width: 700px;
      }
      h2 {
        color: #1a1a2e;
        font-size: 2.5rem;
        margin-bottom: 25px;
      }
      /* Menggunakan font monospace agar lebar karakter sama */
      .typewriter-text {
        color: #4a4a4a;
        font-size: 1.5rem;
        font-weight: 500;
        min-height: 100px; /* Ruang agar tidak 'jump' */
        line-height: 1.5;
        font-family: "Courier New", Courier, monospace;
      }
      .blinking-cursor {
        font-weight: bold;
        color: #667eea;
      }
      button {
        background: #667eea;
        color: white;
        border: none;
        padding: 20px 40px;
        border-radius: 10px;
        font-size: 1.2rem;
        font-weight: bold;
        cursor: pointer;
        margin-top: 30px;
        transition: transform 0.2s ease, background-color 0.2s ease;
      }
      button:hover {
        background: #5a6ecf;
        transform: translateY(-3px);
      }
    </style>
  </head>
  <body>
    <!-- === KONTEN SPESIFIK UNTUK CONTOH INI === -->
    <div class="section">
      <h2>3. Typewriter Effect</h2>
      <p class="typewriter-text">
        <span id="typewriterText"></span><span class="blinking-cursor">|</span>
      </p>
      <button onclick="animateTypewriter()">Jalankan Animasi</button>
    </div>

    <!-- Load GSAP dan TextPlugin dari CDN -->
    <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/TextPlugin.min.js>"></script>

    <script>
      // === JAVASCRIPT SPESIFIK UNTUK CONTOH INI ===

      // Daftarkan TextPlugin agar bisa digunakan oleh GSAP
      gsap.registerPlugin(TextPlugin);

      // Buat cursor berkedip terus-menerus
      gsap.to(".blinking-cursor", {
        opacity: 0,
        duration: 0.5,
        repeat: -1, // -1 berarti loop tak terbatas
        yoyo: true, // Membuatnya kembali ke state semula (muncul-hilang)
        ease: "none",
      });

      function animateTypewriter() {
        const textToType =
          "Ini adalah efek mesin tik yang dibuat dengan GSAP TextPlugin!";
        const targetElement = "#typewriterText";

        // Pastikan teks kosong sebelum memulai
        gsap.set(targetElement, { text: "" });

        // Gunakan `gsap.to` dengan properti `text` dari TextPlugin
        gsap.to(targetElement, {
          duration: textToType.length * 0.05, // Durasi dinamis berdasarkan panjang teks
          text: textToType,
          ease: "none", // 'none' agar kecepatan ketikan konstan
        });
      }
    </script>
  </body>
</html>

Penjelasan:

  1. CDN TextPlugin: Di bagian <script>, sekarang ada dua baris: satu untuk gsap.min.js dan satu lagi untuk TextPlugin.min.js. Ini wajib agar properti text bisa digunakan.
  2. gsap.registerPlugin(TextPlugin): Baris ini memberitahu GSAP untuk mengaktifkan fitur dari TextPlugin yang baru saja kita muat.
  3. Blinking Cursor: Animasi untuk cursor (.blinking-cursor) dijalankan di luar fungsi, sehingga ia akan terus berkedip sejak halaman dimuat. repeat: -1 membuatnya berulang selamanya.
  4. text: textToType: Ini adalah inti dari TextPlugin. Alih-alih memecah teks secara manual, kita cukup memberikan string lengkapnya, dan GSAP akan otomatis menampilkannya huruf demi huruf.Durasi Dinamis:
  5. Durasi animasi (duration) dihitung berdasarkan panjang teks. Semakin panjang teksnya, semakin lama animasinya, membuatnya terasa lebih natural.
Animasi Typewriter
Animasi Typewriter

Text Animation Technique 4: Character by Character dengan Scale

Animation lebih advanced di mana setiap character scale in dengan stagger effect:

character.html

<!DOCTYPE html>
<html lang="id">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>4. GSAP - Character Animation</title>
    <style>
        /* CSS Umum untuk semua contoh (SAMA SEPERTI SEBELUMNYA) */
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            margin: 0;
            background-color: #f0f2f5;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            padding: 20px;
        }
        .section {
            background: white;
            padding: 50px;
            border-radius: 20px;
            box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
            text-align: center;
            width: 90%;
            max-width: 700px;
        }
        h2 {
            color: #1a1a2e;
            font-size: 2.5rem;
            margin-bottom: 25px;
        }
        .character-text {
            color: #4a4a4a;
            font-size: 3rem; /* Font lebih besar agar efek terlihat jelas */
            font-weight: 700;
            min-height: 100px;
            line-height: 1.5;
            letter-spacing: 2px;
        }
        button {
            background: #667eea;
            color: white;
            border: none;
            padding: 20px 40px;
            border-radius: 10px;
            font-size: 1.2rem;
            font-weight: bold;
            cursor: pointer;
            margin-top: 30px;
            transition: transform 0.2s ease, background-color 0.2s ease;
        }
        button:hover {
            background: #5a6ecf;
            transform: translateY(-3px);
        }
    </style>
</head>
<body>

    <!-- === KONTEN SPESIFIK UNTUK CONTOH INI === -->
    <div class="section">
        <h2>4. Character Animation</h2>
        <div class="character-text" id="charText">
            GSAP ROCKS!
        </div>
        <button onclick="animateCharacters()">Jalankan Animasi</button>
    </div>

    <!-- Load GSAP dari CDN -->
    <script src="<https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js>"></script>

    <script>
        // === JAVASCRIPT SPESIFIK UNTUK CONTOH INI ===

        function animateCharacters() {
            const targetElement = document.getElementById("charText");
            const originalText = targetElement.textContent;

            // 1. Memecah teks menjadi array karakter, lalu membungkus setiap karakter
            //    dengan tag <span> agar bisa dianimasikan satu per satu.
            const newHTML = originalText.split('').map(char => {
                // Jika karakter adalah spasi, kita berikan spasi biasa
                if (char === ' ') {
                    return '<span>&nbsp;</span>';
                }
                // Setiap karakter lain dibungkus span dengan style inline
                return `<span style="display: inline-block; opacity: 0; transform: scale(0);">${char}</span>`;
            }).join('');

            // 2. Mengganti konten HTML asli dengan struktur baru
            targetElement.innerHTML = newHTML;

            // 3. Menganimasikan semua <span> yang baru saja dibuat
            gsap.to("#charText span", {
                // State akhir yang dituju:
                opacity: 1,
                scale: 1,

                // Pengaturan Animasi:
                duration: 0.5,
                stagger: 0.05, // Memberi jeda 0.05 detik antar setiap karakter
                ease: "back.out(1.7)" // Efek 'pop' atau 'bounce' yang menarik
            });
        }
    </script>

</body>
</html>

Penjelasan

  1. Manual Splitting: Tidak seperti TextPlugin, di sini kita melakukan pekerjaan secara manual. Kita mengambil teks, memecahnya menjadi huruf-huruf, lalu membungkus setiap huruf dalam tag <span>. Ini adalah konsep fundamental untuk animasi karakter.
  2. Styling di JavaScript: Perhatikan bahwa initial state (kondisi awal) dari animasi (opacity: 0 dan scale: 0) kita set langsung di dalam style inline <span> yang kita buat melalui JavaScript. Kemudian, gsap.to() menganimasikannya menuju kondisi normal (opacity: 1scale: 1).
  3. display: inline-block: Ini penting! <span> secara default adalah elemen inline, yang tidak bisa di-transform (seperti scale atau rotate). Dengan mengubahnya menjadi inline-block, setiap huruf kini bisa kita animasikan transformasinya.
  4. stagger Property: Ini adalah kunci dari efek "satu per satu". Nilai 0.05 berarti animasi untuk karakter kedua akan dimulai 0.05 detik setelah karakter pertama, karakter ketiga 0.05 detik setelah kedua, dan seterusnya, menciptakan efek berurutan yang indah.
Animasi Character
Animasi Character

Text Animation Technique 5: Word by Word Animation

Sometimes kamu ingin animate per-word daripada per-character. Ini perfect untuk paragraf atau body text.

word.html

<!DOCTYPE html>
<html lang="id">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>5. GSAP - Word by Word Animation</title>
    <style>
        /* CSS Umum untuk semua contoh (SAMA SEPERTI SEBELUMNYA) */
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            margin: 0;
            background-color: #f0f2f5;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            padding: 20px;
        }
        .section {
            background: white;
            padding: 50px;
            border-radius: 20px;
            box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
            text-align: center;
            width: 90%;
            max-width: 700px;
        }
        h2 {
            color: #1a1a2e;
            font-size: 2.5rem;
            margin-bottom: 25px;
        }
        .word-text {
            color: #4a4a4a;
            font-size: 1.5rem;
            font-weight: 500;
            min-height: 150px; /* Ruang agar tidak 'jump' */
            line-height: 1.8;
        }
        
        /* CSS Penting untuk Word Animation */
        .word-wrapper {
            display: inline-block;
            overflow: hidden;
            vertical-align: top;
            margin-right: 0.5em; /* Spasi antar wrapper */
        }
        .word-inner {
            display: inline-block;
        }
        
        button {
            background: #667eea;
            color: white;
            border: none;
            padding: 20px 40px;
            border-radius: 10px;
            font-size: 1.2rem;
            font-weight: bold;
            cursor: pointer;
            margin-top: 30px;
            transition: transform 0.2s ease, background-color 0.2s ease;
        }
        button:hover {
            background: #5a6ecf;
            transform: translateY(-3px);
        }
    </style>
</head>
<body>

    <!-- === KONTEN SPESIFIK UNTUK CONTOH INI === -->
    <div class="section">
        <h2>5. Word by Word Animation</h2>
        <p class="word-text" id="wordText">
            <!-- Setiap kata sudah dibungkus dengan dua span -->
            <span class="word-wrapper"><span class="word-inner">Setiap</span></span>
            <span class="word-wrapper"><span class="word-inner">kata</span></span>
            <span class="word-wrapper"><span class="word-inner">dalam</span></span>
            <span class="word-wrapper"><span class="word-inner">kalimat</span></span>
            <span class="word-wrapper"><span class="word-inner">ini</span></span>
            <span class="word-wrapper"><span class="word-inner">akan</span></span>
            <span class="word-wrapper"><span class="word-inner">muncul</span></span>
            <span class="word-wrapper"><span class="word-inner">satu</span></span>
            <span class="word-wrapper"><span class="word-inner">per</span></span>
            <span class="word-wrapper"><span class="word-inner">satu.</span></span>
        </p>
        <button onclick="animateWords()">Jalankan Animasi</button>
    </div>

    <!-- Load GSAP dari CDN -->
    <script src="<https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js>"></script>

    <script>
        // === JAVASCRIPT SPESIFIK UNTUK CONTOH INI ===

        function animateWords() {
            // Kita atur dulu kondisi awalnya menggunakan gsap.set()
            // Ini akan menyembunyikan semua kata sebelum animasi dimulai
            gsap.set("#wordText .word-inner", {
                y: "100%", // Mulai dari posisi 100% di bawah
                opacity: 0
            });
            
            // Sekarang, kita animasikan semua kata 'menuju' kondisi normalnya
            gsap.to("#wordText .word-inner", {
                // State akhir yang dituju:
                y: "0%",
                opacity: 1,

                // Pengaturan Animasi:
                duration: 0.8,
                stagger: 0.1, // Memberi jeda 0.1 detik antar setiap kata
                ease: "power2.out"
            });
        }
    </script>

</body>
</html>

HTML Structure untuk Word by Word:

<p class="word-demo" id="wordText">
    <span class="char-wrap"><span>Word</span></span>
    <span class="char-wrap"><span>One</span></span>
    <span class="char-wrap"><span>Word</span></span>
    <span class="char-wrap"><span>Two</span></span>
</p>
Animasi Word by Word
Animasi Word by Word

Penjelasan:

  1. Struktur HTML Ganda (<span> di dalam <span>):
    • .word-wrapper<span> luar ini memiliki overflow: hidden. Tujuannya adalah untuk bertindak sebagai "jendela" atau mask. Kata-kata yang berada di bawahnya tidak akan terlihat.
    • .word-inner<span> dalam ini yang sebenarnya berisi teks. Inilah yang akan kita gerakkan dari bawah ke atas. Tanpa .word-wrapper, kata-kata akan terlihat muncul dari bawah, yang kurang elegan.
  2. gsap.set(): Sebelum menjalankan animasi utama, kita menggunakan gsap.set() untuk mengatur kondisi awal semua kata. Kita langsung memindahkannya ke bawah (y: "100%") dan membuatnya transparan (opacity: 0) tanpa durasi. Ini memastikan kata-kata tersebut "siap" di posisi start sebelum animasi dipicu.
  3. Animasi gsap.to(): Setelah di-set, kita menganimasikan kata-kata tersebut kembali ke posisi normalnya (y: "0%" dan opacity: 1) dengan efek stagger untuk menciptakan ilusi kemunculan yang berurutan.

Text Animation Technique 6: Color Change Animation

Animate warna teks untuk membuat text lebih vibrant dan engaging:

color.html

<!DOCTYPE html>
<html lang="id">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>6. GSAP - Color Animation</title>
    <style>
        /* CSS Umum untuk semua contoh (SAMA SEPERTI SEBELUMNYA) */
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            margin: 0;
            background-color: #f0f2f5;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            padding: 20px;
        }
        .section {
            background: white;
            padding: 50px;
            border-radius: 20px;
            box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
            text-align: center;
            width: 90%;
            max-width: 700px;
        }
        h2 {
            color: #1a1a2e;
            font-size: 2.5rem;
            margin-bottom: 25px;
        }
        .color-text {
            font-size: 1.8rem; /* Sedikit lebih besar agar warna terlihat */
            font-weight: 700;
            min-height: 60px;
            line-height: 1.5;
            /* Warna awal diambil dari sini */
            color: #667eea;
        }
        button {
            background: #667eea;
            color: white;
            border: none;
            padding: 20px 40px;
            border-radius: 10px;
            font-size: 1.2rem;
            font-weight: bold;
            cursor: pointer;
            margin-top: 30px;
            transition: transform 0.2s ease, background-color 0.2s ease;
        }
        button:hover {
            background: #5a6ecf;
            transform: translateY(-3px);
        }
    </style>
</head>
<body>

    <!-- === KONTEN SPESIFIK UNTUK CONTOH INI === -->
    <div class="section">
        <h2>6. Color Animation</h2>
        <p class="color-text" id="colorText">
            Teks ini akan berubah warna secara terus-menerus.
        </p>
        <button onclick="animateColor()">Jalankan Animasi</button>
    </div>

    <!-- Load GSAP dari CDN -->
    <script src="<https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js>"></script>

    <script>
        // === JAVASCRIPT SPESIFIK UNTUK CONTOH INI ===

        function animateColor() {
            // Kita akan menggunakan timeline untuk membuat urutan animasi warna.
            // Timeline adalah cara terbaik untuk mengontrol beberapa animasi secara berurutan.
            gsap.timeline({
                repeat: -1,         // Ulangi selamanya (-1 berarti loop tak terbatas)
                repeatDelay: 0.5,     // Jeda 0.5 detik sebelum setiap siklus pengulangan
                yoyo: true            // Membuat animasi bolak-balik (A->B->C, lalu C->B->A)
            })
            .to("#colorText", { color: "#e74c3c", duration: 1 }) // Ke Merah
            .to("#colorText", { color: "#3498db", duration: 1 }) // Ke Biru
            .to("#colorText", { color: "#2ecc71", duration: 1 }) // Ke Hijau
            .to("#colorText", { color: "#f1c40f", duration: 1 });// Ke Kuning
        }
    </script>

</body>
</html>
Animasi Color
Animasi Color

Penjelasan:

  1. Tidak Ada Plugin Baru: Animasi warna adalah bagian dari inti GSAP, jadi kita tidak perlu memuat plugin tambahan seperti TextPlugin.
  2. Penggunaan gsap.timeline(): Di sini kita menggunakan gsap.timeline() untuk membuat "wadah" bagi beberapa animasi. Ini memungkinkan kita menjalankan beberapa animasi secara berurutan dengan sangat mudah.
  3. Chaining .to(): Setiap .to() yang kita panggil setelah gsap.timeline() akan otomatis ditambahkan ke akhir urutan. Jadi, animasi akan berubah ke merah, setelah itu berubah ke biru, setelah itu ke hijau, dan seterusnya.
  4. Properti Timeline (repeat dan yoyo):
    • repeat: -1 adalah perintah untuk membuat seluruh urutan animasi di dalam timeline ini berulang tanpa henti.
    • yoyo: true membuat efek "bolak-balik". Setelah mencapai warna kuning, animasi akan berjalan mundur (kuning -> hijau -> biru -> merah) sebelum mengulang lagi dari awal. Ini menciptakan transisi yang sangat halus dan tanpa henti.

Text Animation Technique 7: Stagger Character dengan X Position

Lebih advanced effect di mana character muncul dan bergerak:

stagger.html

<!DOCTYPE html>
<html lang="id">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>7. GSAP - Stagger Animation</title>
    <style>
        /* CSS Umum untuk semua contoh (SAMA SEPERTI SEBELUMNYA) */
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            margin: 0;
            background-color: #f0f2f5;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            padding: 20px;
        }
        .section {
            background: white;
            padding: 50px;
            border-radius: 20px;
            box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
            text-align: center;
            width: 90%;
            max-width: 700px;
        }
        h2 {
            color: #1a1a2e;
            font-size: 2.5rem;
            margin-bottom: 25px;
        }
        .stagger-text {
            color: #4a4a4a;
            font-size: 3rem;
            font-weight: 800; /* Lebih tebal */
            min-height: 100px;
            line-height: 1.5;
            letter-spacing: 3px;
        }
        button {
            background: #667eea;
            color: white;
            border: none;
            padding: 20px 40px;
            border-radius: 10px;
            font-size: 1.2rem;
            font-weight: bold;
            cursor: pointer;
            margin-top: 30px;
            transition: transform 0.2s ease, background-color 0.2s ease;
        }
        button:hover {
            background: #5a6ecf;
            transform: translateY(-3px);
        }
    </style>
</head>
<body>

    <!-- === KONTEN SPESIFIK UNTUK CONTOH INI === -->
    <div class="section">
        <h2>7. Stagger Animation</h2>
        <div class="stagger-text" id="staggerText">
            HELLO WORLD
        </div>
        <button onclick="animateStaggerChars()">Jalankan Animasi</button>
    </div>

    <!-- Load GSAP dari CDN -->
    <script src="<https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js>"></script>

    <script>
        // === JAVASCRIPT SPESIFIK UNTUK CONTOH INI ===

        function animateStaggerChars() {
            const targetElement = document.getElementById("staggerText");
            const originalText = targetElement.textContent;

            // 1. Memecah teks dan membungkus setiap karakter dengan span.
            //    Kita set kondisi awal yang lebih kompleks di sini.
            const newHTML = originalText.split('').map(char => {
                if (char === ' ') {
                    return '<span>&nbsp;</span>';
                }
                // Mulai dari kiri, terbalik (flipped), dan transparan
                return `<span style="display: inline-block; opacity: 0; transform: translateX(-100px) rotateY(180deg);">${char}</span>`;
            }).join('');
            
            targetElement.innerHTML = newHTML;

            // 2. Menganimasikan semua <span> menuju kondisi normal.
            gsap.to("#staggerText span", {
                // State akhir yang dituju:
                x: 0,           // Kembali ke posisi horizontal semula
                rotationY: 0,   // Kembali ke rotasi normal (tidak terbalik)
                opacity: 1,

                // Pengaturan Animasi:
                duration: 0.8,
                stagger: 0.08, // Jeda 0.08 detik antar setiap karakter
                ease: "back.out(1.7)"
            });
        }
    </script>

</body>
</html>
Animasi Stagger
Animasi Stagger

Penjelasan

  1. Kondisi Awal yang Kompleks: Di dalam animateStaggerChars(), perhatikan style inline pada <span> yang kita buat: transform: translateX(-100px) rotateY(180deg);. Ini berarti setiap huruf akan memulai animasinya dari:
    • 100 piksel di sebelah kiri (translateX(-100px)).
    • Dalam keadaan terbalik secara horizontal (rotateY(180deg)).
    • Dan transparan (opacity: 0).
  2. Animasi Transformgsap.to() kemudian menganimasikan semua properti tersebut kembali ke nilai normalnya (x: 0rotationY: 0opacity: 1).
  3. Efek 3D: Kombinasi translateX dan rotateY memberikan ilusi gerakan 3D yang sangat menarik saat huruf-huruf "terbang" dan "membalik" ke posisinya.
  4. Stagger Tetap Kunci: Properti stagger sekali lagi menjadi kunci yang membuat efek ini terlihat seperti gelombang yang mengalir, bukan semua huruf bergerak bersamaan.

Text Animation Technique 8: Scale & Rotate dengan Bounce

Fun effect di mana teks scale dan rotate dengan bounce:

scale.html

<!DOCTYPE html>
<html lang="id">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>8. GSAP - Scale & Rotate Animation</title>
    <style>
        /* CSS Umum untuk semua contoh (SAMA SEPERTI SEBELUMNYA) */
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            margin: 0;
            background-color: #f0f2f5;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            padding: 20px;
        }
        .section {
            background: white;
            padding: 50px;
            border-radius: 20px;
            box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
            text-align: center;
            width: 90%;
            max-width: 700px;
        }
        h2 {
            color: #1a1a2e;
            font-size: 2.5rem;
            margin-bottom: 25px;
        }
        .scale-text {
            color: #4a4a4a;
            font-size: 4rem; /* Sangat besar agar efek terlihat dramatis */
            font-weight: 900; /* Super tebal */
            min-height: 120px;
            line-height: 1.5;
            letter-spacing: 4px;
            text-transform: uppercase;
        }
        button {
            background: #667eea;
            color: white;
            border: none;
            padding: 20px 40px;
            border-radius: 10px;
            font-size: 1.2rem;
            font-weight: bold;
            cursor: pointer;
            margin-top: 30px;
            transition: transform 0.2s ease, background-color 0.2s ease;
        }
        button:hover {
            background: #5a6ecf;
            transform: translateY(-3px);
        }
    </style>
</head>
<body>

    <!-- === KONTEN SPESIFIK UNTUK CONTOH INI === -->
    <div class="section">
        <h2>8. Scale & Rotate Animation</h2>
        <div class="scale-text" id="scaleText">
            DYNAMIC
        </div>
        <button onclick="animateScaleText()">Jalankan Animasi</button>
    </div>

    <!-- Load GSAP dari CDN -->
    <script src="<https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js>"></script>

    <script>
        // === JAVASCRIPT SPESIFIK UNTUK CONTOH INI ===

        function animateScaleText() {
            // Kita animasikan seluruh elemen div, bukan karakter satu per satu.
            gsap.from("#scaleText", {
                // Mulai dari state:
                scale: 0.5,           // Ukuran 50% dari ukuran normal
                rotation: 90,        // Terputar 90 derajat
                opacity: 0,

                // Pengaturan Animasi:
                duration: 1.5,
                ease: "elastic.out(1, 0.4)" // Efek 'elastis' seperti pegas
            });
        }
    </script>

</body>
</html>
Animasi Scale and Rotate Dinamis
Animasi Scale and Rotate Dinamis

Penjelasan

  1. Target Animasi: Tidak seperti contoh karakter, di sini kita menargetkan seluruh div dengan id="scaleText". Ini berarti seluruh kata "DYNAMIC" akan beranimasi sebagai satu kesatuan.
  2. Kombinasi scale dan rotation: Properti scale: 0.5 memulai animasi dari setengah ukuran, dan rotation: 90 memulainya dari posisi terputar 90 derajat. GSAP akan menganimasikan keduanya secara bersamaan kembali ke nilai normal (scale: 1rotation: 0).
  3. ease: "elastic.out(1, 0.4)": Ini adalah bintang utama dari contoh ini.
    • elastic.out adalah easing yang menciptakan efek seperti benda elastis yang ditarik lalu dilepaskan, sehingga "memantul" beberapa kali sebelum berhenti.
    • Angka pertama (1) mengontrol amplitude atau seberapa kuat pantulannya.
    • Angka kedua (0.4) mengontrol period atau seberapa cepat pantulannya. Anda bisa mengubah angka-angka ini untuk mendapatkan efek yang berbeda.

Tips & Best Practices untuk Text Animation

1. Durasi yang Tepat

  • Fast typing: 0.05 - 0.1s per character
  • Normal typing: 0.1 - 0.15s per character
  • Slow/dramatic: 0.2s+ per character

2. Gunakan Easing yang Tepat

  • Typewriter effect: ease: "none" (linear)
  • Entrance animations: ease: "power2.out" atau "back.out"
  • Bouncy effects: ease: "elastic.out"

3. Performance Considerations

  • Animate opacity dan transform properties (GPU accelerated)
  • Hindari animasi properties yang trigger layout reflow seperti widthheight
  • Kalau character terlalu banyak (>100), consider menggunakan will-change CSS

css.animated-text { will-change: opacity, transform; }

4. Accessibility

  • Jangan bikin text animation terlalu fast sampai susah dibaca
  • Provide option untuk disable animations untuk users dengan motion sensitivity
  • Selalu pastikan text readable bahkan sebelum animation complete

5. Mobile Optimization

  • Kurangi durasi di mobile untuk feel lebih responsive
  • Gunakan simpler animations di mobile (hindari character-by-character untuk text panjang)
  • Test di real mobile devices

Contoh Lengkap: Landing Page Hero Section

*// Initialize hero animations*
function initHeroAnimations() {
    const tl = gsap.timeline();
    
    *// Animate title character by character*
    tl.from(".hero-title span", {
        opacity: 0,
        y: 20,
        stagger: 0.05,
        duration: 0.4,
        ease: "back.out(2)"
    })
    
    *// Animate subtitle with delay*
    .from(".hero-subtitle", {
        opacity: 0,
        y: 20,
        duration: 0.8,
        ease: "power2.out"
    }, "-=0.3")
    
    *// Animate CTA button*
    .from(".cta-button", {
        opacity: 0,
        scale: 0.8,
        duration: 0.5,
        ease: "back.out(2)"
    }, "-=0.2");
}

*// Jalankan saat page load*
window.addEventListener("load", initHeroAnimations);
Hero Landing Page
Hero Landing Page

Tapi ini akan kita bahas di lain waktu.

Kesimpulan

Text animation dengan GSAP membuka dunia kemungkinan untuk membuat website yang lebih engaging dan memorable. Dari simple fade-in sampai complex typewriter effects, GSAP memberikan tools yang powerful namun mudah digunakan.

Key takeaways:

  • Start dengan simple animations (fade, slide)
  • Gradually explore yang lebih complex (character by character, typewriter)
  • Always prioritize readability dan user experience
  • Test di berbagai devices untuk ensure smooth performance
  • Combine text animations dengan timeline untuk create cohesive animation sequences

Jangan takut untuk experiment dengan berbagai kombinasi properties, easing functions, dan stagger values. Setiap combination bisa create unique effects yang membuat website kamu stand out!

Happy text animating! 🎨✨