→ פרק קודם: SVG — גרפיקה וקטורית | פרק הבא: Canvas ←

פרק 9: Lottie & Rive — אנימציות מוכנות מ-After Effects ועד הדפדפן

בפרק 8 למדתם SVG — איך לצייר גרפיקה וקטורית בדפדפן ולהנפיש אותה עם CSS ו-GSAP. עכשיו שאלה חשובה: מה קורה כשאתם צריכים אנימציה מורכבת — דמות שמנופפת, אייקון שמשתנה, מעבר loading מרשים — אבל אין לכם את הזמן או המיומנות ליצור אותה מאפס? התשובה: אנימציות מוכנות. Lottie לוקח אנימציות שנוצרו ב-After Effects ומנגן אותן בדפדפן כקבצי JSON קלי משקל. Rive הולך צעד קדימה — הוא מאפשר ליצור אנימציות אינטראקטיביות עם state machines, כך שהאנימציה מגיבה ל-hover, click, ומצבי אפליקציה בזמן אמת. בפרק הזה תלמדו את שניהם: מתי להשתמש ב-Lottie, מתי ב-Rive, ואיך לשלב אנימציות מוכנות בפרויקטים שלכם — עם קוד מינימלי ותוצאות מקסימליות.

מה תקבלו בסוף הפרק
מה תוכלו לעשות אחרי הפרק
לפני שמתחילים
הפרויקט שלך

בפרק 8 בניתם אנימציות SVG — morphing, draw-on, ואייקונים אנימטיביים. בפרק הזה תוסיפו שכבה חדשה: אנימציות מוכנות שמעלות את הרמה בלי לכתוב הכל מאפס. תשלבו Lottie animation ב-hero section שלכם (loading או success indicator), תוסיפו empty state אנימטיבי עם Lottie, ותבנו אנימציה אינטראקטיבית אחת עם Rive שמגיבה ל-hover ו-click. בפרק 10 תלמדו Canvas — ציור פיקסלי לאנימציות שגם SVG וגם Lottie לא יכולים לעשות.

מילון מונחים
מונח (English)תרגוםהגדרה
Lottieלוטיפורמט אנימציה מבוסס JSON שנוצר על ידי Airbnb. מאפשר לנגן אנימציות After Effects בדפדפן, באפליקציות mobile ובכל פלטפורמה — בגודל קובץ זעיר
Riveרייבפלטפורמה ליצירת אנימציות אינטראקטיביות עם state machines. מאפשר ליצור אנימציות שמגיבות לקלט משתמש בזמן אמת — דבר ש-Lottie לא תומך בו באופן מקורי
BodymovinבודימוביןPlugin ל-Adobe After Effects שמייצא אנימציות לפורמט Lottie JSON. הגשר בין עולם ה-motion design לעולם ה-web
LottieFilesלוטיפיילסMarketplace ופלטפורמה לאנימציות Lottie — חיפוש, תצוגה מקדימה, התאמה אישית, והורדה. אלפי אנימציות חינמיות ובתשלום
state machineמכונת מצביםמודל שמגדיר מצבים (idle, hover, click, success) ומעברים ביניהם. ב-Rive, state machines שולטים באנימציה — כל מצב מנגן אנימציה אחרת
artboardלוח עבודהב-Rive, ה-canvas שבו מעצבים את האנימציה. כל artboard יכול להכיל מספר state machines ואנימציות. דומה ל-layer ב-Photoshop
dotlottie (.lottie)דוט-לוטיפורמט חדש של Lottie — קובץ דחוס (ZIP) שמכיל JSON + assets. קטן עד פי 10 מ-JSON רגיל, ותומך בכמה אנימציות בקובץ אחד
lottie-playerנגן לוטיWeb component רשמי של LottieFiles — תג HTML <lottie-player> שמנגן אנימציות Lottie. הדרך הפשוטה ביותר לשלב Lottie באתר
rive-reactרייב-ריאקטספריית React רשמית של Rive — hook useRive שמנגן אנימציות Rive בתוך קומפוננטת React עם שליטה מלאה ב-state machine
After Effectsאפטר אפקטסתוכנת motion design מקצועית של Adobe — הכלי הסטנדרטי ליצירת אנימציות מורכבות. Bodymovin מייצא אנימציות AE לפורמט Lottie
keyframe exportייצוא מפתחותהתהליך שבו Bodymovin ממיר keyframes מ-After Effects ל-JSON — כל keyframe הופך לאובייקט JSON עם זמן, ערך, ו-easing
segmentמקטעחלק מאנימציית Lottie — מוגדר על ידי frame התחלה ו-frame סיום. מאפשר לנגן רק חלק מהאנימציה, למשל רק את ה-hover state
מתחיל 6 דקות מושג

9.1 מה זה אנימציות מוכנות — ולמה לא לקודד הכל מאפס

עד עכשיו בקורס הזה, כל אנימציה שבניתם — כתבתם בעצמכם. CSS transitions, GSAP tweens, SVG morphing — קוד שאתם שולטים בכל שורה שלו. וזה מצוין! אבל בעולם האמיתי, יש סוגים של אנימציות שפשוט לא שווה לבנות מאפס.

תחשבו על זה: אנימציית loading מורכבת עם 15 אלמנטים שזוחלים, מסתובבים ומשנים צבעים? זה 200+ שורות CSS או GSAP. דמות מצוירת שמנופפת ביד? אין סיכוי בקוד בלבד — צריך שרטוט, rigging, ו-frame-by-frame animation. אייקון שמשנה צורה מ-hamburger ל-X עם 12 keyframes חלקים? אפשר בקוד, אבל motion designer עם After Effects יעשה את זה טוב יותר בחצי מהזמן.

אנימציות מוכנות (pre-made animations) פותרות את הבעיה הזו. הן נוצרות בכלי עיצוב מקצועיים — After Effects, Rive Editor, Figma — ואז מיוצאות לפורמט שהדפדפן יכול לנגן. אתם לא צריכים לדעת motion design — אתם צריכים לדעת איך לשלב את האנימציה בקוד שלכם.

שתי הטכנולוגיות הדומיננטיות בתחום הזה הן:

Framework: מתי לקודד ומתי להשתמש באנימציה מוכנה
קריטריוןקודד בעצמך (CSS/GSAP/SVG)אנימציה מוכנה (Lottie/Rive)
מורכבות ויזואליתאלמנטים גיאומטריים פשוטים — קוים, עיגולים, מלבנים, טקסטאיורים, דמויות, אנימציות עם עשרות אלמנטים, אפקטים אורגניים
שליטה בזמן ריצהשליטה מלאה בכל פרמטר — אתם כותבים הכלשליטה דרך API: play, pause, speed, segments, state inputs
גודל קובץאפס — הקוד כבר בבאנדל5KB-200KB (Lottie JSON) / 2KB-50KB (.riv)
זמן פיתוחתלוי במורכבות — דקות עד שעותדקות — מורידים, משלבים, מתאימים
אינטראקטיביותכל דבר שתקודדוLottie: מוגבלת. Rive: state machines מלאים
תלות חיצוניתאפס (CSS) או GSAP (JS)lottie-web (~250KB) או @rive-app/canvas (~150KB)

כלל אצבע: אם אתם יכולים לתאר את האנימציה ב-3 שורות — קודדו. אם אתם צריכים ציור כדי להסביר אותה — חפשו אנימציה מוכנה.

2 דקות עשו עכשיו: הכירו את שני העולמות
  1. פתחו LottieFiles Featured — גללו ותראו את סוגי האנימציות. לחצו על 2-3 שמושכות את העין
  2. פתחו Rive Community — שימו לב: האנימציות כאן מגיבות ל-hover ו-click. העבירו את העכבר ולחצו
  3. שימו לב להבדל: ב-LottieFiles האנימציות רצות בלופ. ב-Rive הן מגיבות לכם. זה ההבדל המרכזי

חשוב להבין: Lottie ו-Rive הם לא מתחרים — הם משלימים. Lottie מצוין כשצריך אנימציה יפה שרצה — loading, success indicator, אייקון אנימטיבי, הנפשת דמות. Rive מצוין כשהאנימציה צריכה להגיב — כפתור שמשנה מצב, avatar שעוקב אחרי העכבר, game-like interaction. ברוב הפרויקטים תשתמשו בשניהם — Lottie לאנימציות "רקע" ו-Rive לאנימציות "אינטראקטיביות".

מתחיל 8 דקות כלי

9.2 Lottie — מ-After Effects לדפדפן דרך JSON

Lottie נולד ב-2017 כפרויקט פנימי של Airbnb. הצוות רצה אנימציות עשירות באפליקציית המובייל — אבל GIF היו כבדים מדי, וידאו היה יקר, ו-CSS animations היו מוגבלות. הפתרון: plugin ל-After Effects (בשם Bodymovin) שמייצא את האנימציה כ-JSON, ונגן קל שמנגן את ה-JSON בזמן ריצה.

איך Lottie עובד — הצינור המלא:

  1. יצירה ב-After Effects — מעצב/ת motion design יוצר/ת אנימציה ב-AE. שכבות, keyframes, easing, masks, shape layers, trim paths — כל הכלים המקצועיים
  2. ייצוא עם Bodymovin — Plugin ל-AE שממיר את האנימציה ל-JSON. כל keyframe הופך לאובייקט, כל שכבה הופכת לנתיב SVG, כל easing curve נשמר כ-bezier values
  3. קובץ JSON — הפלט הוא קובץ JSON שמכיל את כל נתוני האנימציה. גודל טיפוסי: 5KB-200KB (בהשוואה ל-GIF שיכול להיות 2MB+ על אותה אנימציה)
  4. ניגון בדפדפן — ספריית lottie-web (או lottie-player web component) קוראת את ה-JSON ומרנדרת את האנימציה — כ-SVG, Canvas, או HTML — בזמן אמת

ככה נראה Lottie JSON מבפנים (גרסה מקוצרת מאוד):

// מבנה בסיסי של Lottie JSON
{
  "v": "5.7.1",           // גרסת Bodymovin
  "fr": 30,               // frame rate (30fps)
  "ip": 0,                // in-point (frame התחלה)
  "op": 60,               // out-point (frame סיום) → 60/30 = 2 שניות
  "w": 200,               // רוחב
  "h": 200,               // גובה
  "layers": [             // שכבות האנימציה
    {
      "ty": 4,            // סוג שכבה: 4 = shape layer
      "nm": "Circle",     // שם השכבה
      "ks": {             // keyframes לכל property
        "o": { "a": 1, "k": [/* opacity keyframes */] },
        "p": { "a": 1, "k": [/* position keyframes */] },
        "s": { "a": 1, "k": [/* scale keyframes */] }
      },
      "shapes": [/* SVG path data */]
    }
  ]
}

מה שמדהים בפורמט הזה: הוא וקטורי. כמו SVG, Lottie מבוסס על נתיבים מתמטיים — לא פיקסלים. זה אומר שהאנימציה נראית חדה בכל רזולוציה, בכל גודל מסך. ובגלל שזה JSON — אפשר לדחוס אותו עם gzip ולהקטין עוד 60-70%.

אזהרה: לא כל After Effects נתמך

Bodymovin לא תומך ב-100% מהפיצ'רים של After Effects. אפקטים כמו 3D camera, complex expressions, blur/glow, ו-track mattes מסוימים — לא ייוצאו כמו שצריך. כש-Lottie animation נראית שבורה, זו בדרך כלל הסיבה. תמיד בדקו ב-LottieFiles Preview לפני שמשלבים באתר. אם אתם עובדים עם motion designer — בקשו שישתמש רק ב-features נתמכים (shape layers, trim paths, masks, basic effects).

3 דקות עשו עכשיו: ראו Lottie JSON בפעולה
  1. פתחו LottieFiles — Loading animations
  2. בחרו אנימציית loading אחת שמוצאת חן בעיניכם
  3. לחצו על "Download" ובחרו "Lottie JSON". פתחו את הקובץ ב-editor (VS Code / אפילו Notepad) — תראו את המבנה שלמעלה
  4. חזרו ל-LottieFiles ולחצו על "HTML" — תראו את קוד ה-embed שנצטרך בסעיף הבא

שלושת הרנדרים של Lottie: lottie-web תומך ב-3 מצבי רינדור:

בפועל, SVG הוא כמעט תמיד הבחירה הנכונה. Canvas שווה רק כשיש אנימציות מאוד כבדות (50+ שכבות) והביצועים סובלים. HTML כמעט לא בשימוש ב-2026.

מתחיל 7 דקות כלי

9.3 LottieFiles — השוק הכי גדול לאנימציות מוכנות

LottieFiles הוא ל-Lottie מה ש-Unsplash הוא לתמונות — marketplace ענק שבו מעצבים מעלים אנימציות, ומפתחים מורידים ומשלבים. נכון ל-2026, יש ב-LottieFiles יותר מ-200,000 אנימציות, רובן חינמיות. זה המקום הראשון שתחפשו בו כשצריכים אנימציית Lottie.

חיפוש חכם ב-LottieFiles:

LottieFiles Editor — התאמה אישית בלי After Effects:

אחד הפיצ'רים הכי שימושיים של LottieFiles הוא ה-Editor המובנה. אחרי שבחרתם אנימציה, אפשר:

5 דקות עשו עכשיו: התאימו אנימציה ל-brand שלכם
  1. חפשו ב-LottieFiles: "success checkmark"
  2. בחרו אנימציה שמוצאת חן בעיניכם ולחצו עליה
  3. לחצו על "Edit" (או "Customize") — שנו את הצבע הראשי לצבע ה-brand שלכם (או כל צבע שתרצו)
  4. שנו את המהירות ל-0.5x (איטי יותר) ותראו איך זה משפיע על התחושה
  5. הורידו את הקובץ כ-Lottie JSON — נשתמש בו בסעיף הבא
אזהרה: רישיונות — תבדקו לפני שמשלבים

רוב האנימציות ב-LottieFiles הן "Free" — אבל יש הבדל בין "free for personal use" לבין "free for commercial use". תמיד בדקו את הרישיון של האנימציה הספציפית. אנימציות Premium דורשות מנוי ($). אם אתם בונים מוצר מסחרי — השקיעו ב-Premium או בדקו שהרישיון החינמי מאפשר שימוש מסחרי. אל תניחו — תבדקו.

בינוני 10 דקות קוד

9.4 שילוב Lottie באתר — מ-Web Component עד React

יש שלוש דרכים עיקריות לשלב Lottie באתר. נתחיל מהפשוטה ביותר ונתקדם:

דרך 1: lottie-player Web Component (הכי פשוט)

lottie-player הוא web component רשמי של LottieFiles. תג HTML אחד — וזה עובד. זו הדרך המומלצת לרוב הפרויקטים:

<!-- שלב 1: טעינת הספרייה (פעם אחת, ב-head או לפני הסגירה של body) -->
<script src="https://unpkg.com/@lottiefiles/lottie-player@2/dist/lottie-player.js"></script>

<!-- שלב 2: שימוש ב-web component -->
<lottie-player
  src="https://lottiefiles.com/animations/success-check"
  background="transparent"
  speed="1"
  style="width: 300px; height: 300px;"
  loop
  autoplay
></lottie-player>

הפרמטרים העיקריים:

דרך 2: lottie-web ישירות (יותר שליטה)

lottie-web היא הספרייה שמאחורי lottie-player. אם צריכים שליטה מלאה — אפשר להשתמש בה ישירות:

// התקנה: npm install lottie-web
import lottie from 'lottie-web';

// יצירת instance
const animation = lottie.loadAnimation({
  container: document.getElementById('lottie-container'),
  renderer: 'svg',        // 'svg' | 'canvas' | 'html'
  loop: true,
  autoplay: true,
  path: '/animations/loading.json'  // URL לקובץ JSON
  // או: animationData: jsonObject   // JSON ישירות (בלי network request)
});

// שליטה בסיסית
animation.play();
animation.pause();
animation.stop();
animation.setSpeed(1.5);           // מהירות
animation.setDirection(-1);        // אחורה
animation.goToAndStop(30, true);   // קפוץ ל-frame 30 ועצור
animation.goToAndPlay(0, true);    // קפוץ ל-frame 0 והתחל

// events
animation.addEventListener('complete', () => {
  console.log('Animation finished!');
});
animation.addEventListener('loopComplete', () => {
  console.log('Loop completed');
});

דרך 3: React עם @lottiefiles/react-lottie-player

// התקנה: npm install @lottiefiles/react-lottie-player
import { Player } from '@lottiefiles/react-lottie-player';

function SuccessAnimation() {
  return (
    <Player
      autoplay
      loop={false}
      src="/animations/success.json"
      style={{ height: '200px', width: '200px' }}
      onEvent={(event) => {
        if (event === 'complete') {
          console.log('Animation done!');
        }
      }}
    />
  );
}

// עם ref לשליטה מלאה
import { useRef } from 'react';

function ControlledAnimation() {
  const playerRef = useRef(null);

  return (
    <div>
      <Player
        ref={playerRef}
        src="/animations/toggle.json"
        style={{ height: '100px', width: '100px' }}
      />
      <button onClick={() => playerRef.current?.play()}>Play</button>
      <button onClick={() => playerRef.current?.pause()}>Pause</button>
    </div>
  );
}

דרך 4: dotlottie — הפורמט החדש והקל

dotlottie (.lottie) הוא פורמט חדש יותר — קובץ דחוס (ZIP) שמכיל את ה-JSON + assets (תמונות, פונטים). היתרונות:

<!-- dotlottie player -->
<script src="https://unpkg.com/@dotlottie/player-component@2/dist/dotlottie-player.mjs" type="module"></script>

<dotlottie-player
  src="/animations/hero.lottie"
  background="transparent"
  speed="1"
  style="width: 400px; height: 400px;"
  loop
  autoplay
></dotlottie-player>
15 דקות תרגיל: שלבו אנימציית Lottie בדף
  1. פתחו CodePen חדש (או פרויקט מקומי)
  2. הוסיפו את script tag של lottie-player (מהקוד למעלה)
  3. חפשו ב-LottieFiles אנימציה שמתאימה לפרויקט שלכם (loading, success, empty state)
  4. העתיקו את ה-URL של ה-JSON ושימו ב-src של lottie-player
  5. הגדירו: width ו-height מתאימים, background="transparent", loop ו-autoplay
  6. נסו לשנות speed ל-0.5 ול-2 — שימו לב לתחושה השונה
  7. בונוס: הוסיפו כפתור שמפעיל/עוצר את האנימציה דרך JavaScript (player.play() / player.pause())

קריטריון הצלחה: אנימציית Lottie רצה בדף שלכם, בגודל מתאים, עם background שקוף.

אזהרה: גודל הספרייה — lottie-web הוא 250KB+

lottie-web (הספרייה שמרנדרת Lottie) שוקלת כ-250KB (minified). זה לא מעט! אם הדף שלכם טוען אנימציית Lottie אחת קטנה — אתם עלולים לטעון 250KB של JavaScript עבור אנימציה של 10KB. שתי אסטרטגיות: (1) השתמשו ב-lottie-light (150KB, בלי expressions ו-canvas renderer) אם מספיק. (2) טענו את lottie-player רק כשצריך — lazy loading עם Intersection Observer (סעיף 9.11). אל תטענו את הספרייה ב-head אם האנימציה ב-footer.

בינוני 10 דקות קוד

9.5 אינטראקטיביות עם Lottie — scroll, hover, click ו-segments

Lottie "וניל" הוא play-and-forget — האנימציה רצה ואתם צופים. אבל עם קצת JavaScript, אפשר להפוך אנימציית Lottie לאינטראקטיבית: להפעיל ב-scroll, לנגן segment ב-hover, לשלוט ב-speed ב-click, ולקשר את ההתקדמות לפעולות משתמש.

תבנית 1: Play on scroll (Intersection Observer)

// האנימציה מתחילה רק כשהאלמנט נכנס ל-viewport
const player = document.querySelector('lottie-player');

// בהתחלה — עצורה
player.removeAttribute('autoplay');

const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      player.play();
      observer.unobserve(entry.target); // פעם אחת בלבד
    }
  });
}, { threshold: 0.5 }); // 50% מהאלמנט נראה

observer.observe(player);

תבנית 2: Scroll-driven — התקדמות צמודה לגלילה

// האנימציה מתקדמת לפי מיקום הגלילה
const player = document.querySelector('lottie-player');
const container = document.getElementById('scroll-container');

// חישוב אחוז הגלילה
function updateAnimation() {
  const rect = container.getBoundingClientRect();
  const scrollPercent = Math.max(0, Math.min(1,
    (window.innerHeight - rect.top) / (window.innerHeight + rect.height)
  ));

  // המרה ל-frame
  const totalFrames = player.getLottie().totalFrames;
  const frame = Math.floor(scrollPercent * totalFrames);
  player.getLottie().goToAndStop(frame, true);
}

// ביצועים: requestAnimationFrame + passive listener
let ticking = false;
window.addEventListener('scroll', () => {
  if (!ticking) {
    requestAnimationFrame(() => {
      updateAnimation();
      ticking = false;
    });
    ticking = true;
  }
}, { passive: true });

תבנית 3: Hover — נגן segment

// ב-hover: נגן frames 0-30 (הופעה)
// ב-leave: נגן frames 30-60 (היעלמות)
const player = document.querySelector('lottie-player');
const lottieInstance = player.getLottie();

player.addEventListener('mouseenter', () => {
  lottieInstance.playSegments([0, 30], true);
});

player.addEventListener('mouseleave', () => {
  lottieInstance.playSegments([30, 60], true);
});

// true = force — מתחיל מיד, בלי להמתין לסיום הסגמנט הנוכחי

תבנית 4: Click toggle — מעבר בין מצבים

// לחיצה מחליפה בין "on" (frames 0-30) ל-"off" (frames 30-60)
const player = document.querySelector('lottie-player');
const lottieInstance = player.getLottie();
let isOn = false;

player.addEventListener('click', () => {
  if (isOn) {
    lottieInstance.playSegments([30, 60], true);
  } else {
    lottieInstance.playSegments([0, 30], true);
  }
  isOn = !isOn;
});

תבנית 5: Speed control — שליטה דינמית במהירות

// מהירות האנימציה משתנה לפי מיקום העכבר
const player = document.querySelector('lottie-player');
const lottieInstance = player.getLottie();

document.addEventListener('mousemove', (e) => {
  // מהירות 0.5x בצד שמאל, 3x בצד ימין
  const speed = 0.5 + (e.clientX / window.innerWidth) * 2.5;
  lottieInstance.setSpeed(speed);
});
5 דקות עשו עכשיו: hover interaction על Lottie
  1. קחו את ה-CodePen מהתרגיל הקודם (או פתחו חדש)
  2. הסירו את autoplay מה-lottie-player
  3. הוסיפו JavaScript שמפעיל play() ב-mouseenter ו-stop() ב-mouseleave
  4. בדקו: האנימציה מתחילה כשמעבירים את העכבר ועוצרת כשעוזבים
  5. שדרוג: במקום play/stop, נסו playSegments — נגנו רק חצי מהאנימציה ב-hover

@lottiefiles/lottie-interactivity — ספריית אינטראקטיביות מוכנה:

אם אתם צריכים אינטראקטיביות בלי לכתוב JavaScript מאפס, LottieFiles מציעים ספרייה ייעודית:

<!-- טעינה -->
<script src="https://unpkg.com/@lottiefiles/lottie-interactivity@latest/dist/lottie-interactivity.min.js"></script>

<!-- שימוש: play on scroll -->
<lottie-player
  id="scroll-lottie"
  src="/animations/progress.json"
  style="width: 300px;"
></lottie-player>

<script>
LottieInteractivity.create({
  player: '#scroll-lottie',
  mode: 'scroll',
  actions: [
    {
      visibility: [0, 1],       // 0% עד 100% visibility
      type: 'seek',             // התקדמות צמודה לגלילה
      frames: [0, 120]          // frames להתקדמות
    }
  ]
});
</script>

הספרייה תומכת גם ב-cursor position (אנימציה שעוקבת אחרי העכבר), click toggle, ו-chain (רצף פעולות). זו דרך מצוינת להוסיף אינטראקטיביות בלי לכתוב event handlers בעצמכם.

בינוני 8 דקות מושג

9.6 Rive — מכונות מצבים לאנימציה אינטראקטיבית

Lottie הוא "נגן" — הוא מנגן אנימציה מ-A ל-Z, ואתם שולטים ב-play/pause. Rive הוא "מנוע" — הוא מריץ state machine שיודע להחליט לבד מה לנגן, בהתאם לקלט שהוא מקבל.

ההבדל הזה הוא מהותי. עם Lottie, אם אתם רוצים כפתור שמנפיש hover, click, ו-loading — אתם צריכים לנהל 3 segments ב-JavaScript, לעקוב אחרי state, ולטפל ב-edge cases (מה קורה אם לוחצים בזמן hover? מה אם ה-loading מסתיים בזמן mouseleave?). עם Rive, כל הלוגיקה הזו מוגדרת בתוך האנימציה עצמה — ה-state machine יודע לנהל מעברים, priorities, ו-blending.

מה Rive יכול לעשות ש-Lottie לא:

מתי Rive עדיף על Lottie?

3 דקות עשו עכשיו: חוו את ההבדל
  1. פתחו Rive Community: Login Character (או חפשו "login character" ב-Rive Community)
  2. הקלידו בשדה הטקסט — שימו לב: הדמות עוקבת אחרי מה שאתם מקלידים
  3. לחצו על שדה הסיסמה — הדמות מכסה את העיניים
  4. זה state machine בפעולה: הדמות מגיבה ל-inputs שונים (focus על שדות שונים, טקסט, הצלחה/כשלון) — בלי שום JavaScript שלכם מנהל את המעברים

איך Rive עובד — ארכיטקטורה:

// הזרימה של Rive
[Rive Editor] → [.riv file] → [Rive Runtime] → [Canvas/WebGL]

// המבנה הפנימי
Artboard (לוח עבודה)
  ├── Animations (אנימציות בסיסיות)
  │     ├── idle      — אנימציית idle (רגיעה)
  │     ├── hover     — אנימציית hover
  │     ├── click     — אנימציית לחיצה
  │     └── success   — אנימציית הצלחה
  │
  └── State Machine (מכונת מצבים)
        ├── States (מצבים)
        │     ├── Idle State      → מנגן: idle animation
        │     ├── Hover State     → מנגן: hover animation
        │     ├── Pressed State   → מנגן: click animation
        │     └── Success State   → מנגן: success animation
        │
        ├── Transitions (מעברים)
        │     ├── Idle → Hover    (כש-isHovered = true)
        │     ├── Hover → Pressed (כש-trigger "click" מופעל)
        │     └── Pressed → Success (כש-isSuccess = true)
        │
        └── Inputs (קלטים)
              ├── isHovered: Boolean
              ├── click: Trigger
              └── isSuccess: Boolean

הנקודה המרכזית: ב-Lottie, אתם (המפתח) מנהלים את כל הלוגיקה ב-JavaScript. ב-Rive, ה-state machine מנהל — ואתם רק שולחים inputs. זה הופך את הקוד ליותר נקי, יותר maintainable, ופחות prone to bugs.

בינוני 8 דקות כלי

9.7 Rive Editor — artboards, state machines ו-transitions

Rive Editor הוא כלי עיצוב שרץ בדפדפן (rive.app). זה לא After Effects — הוא נבנה מאפס לאנימציות אינטראקטיביות ב-web. אתם לא צריכים להתקין שום דבר, וה-free plan נדיב מספיק לרוב הפרויקטים.

המושגים המרכזיים ב-Rive Editor:

1. Artboard — לוח העבודה

ה-artboard הוא ה-canvas שבו מעצבים. כל artboard הוא אנימציה עצמאית עם גודל, רקע, ומבנה משלו. קובץ .riv אחד יכול להכיל כמה artboards — למשל, artboard לכפתור ו-artboard ל-icon.

2. Animations — אנימציות בסיסיות

כל artboard מכיל אנימציות — רצפי keyframes שמנפישים properties. זה דומה ל-timeline של GSAP:

3. State Machine — הלב של Rive

ה-state machine מחבר את האנימציות ללוגיקה. זה הדבר שהופך Rive ל-Rive:

// שלושת סוגי ה-inputs ב-Rive
Boolean  — true/false. דוגמה: isHovered, isActive, isDark
Number   — ערך מספרי. דוגמה: progress (0-100), mouseX, scrollPercent
Trigger  — one-shot event. דוגמה: "click", "submit", "reset"

// ההבדל בין Boolean ל-Trigger:
// Boolean = מצב מתמשך. "העכבר מעל הכפתור" (isHovered = true)
// Trigger = אירוע חד-פעמי. "המשתמש לחץ" (fire trigger "click")

4. Transitions — מעברים בין states

כל transition מוגדר עם:

20 דקות תרגיל: בנו state machine בסיסי ב-Rive
  1. פתחו Rive Editor (צרו חשבון חינם אם אין לכם)
  2. צרו artboard חדש, 200x200 פיקסלים
  3. ציירו עיגול פשוט (Ellipse tool) במרכז ה-artboard
  4. צרו 2 אנימציות: "idle" (העיגול נושם — scale 1 → 1.1 → 1 בלופ) ו-"hover" (העיגול גדל — scale 1 → 1.3 עם שינוי צבע)
  5. צרו State Machine חדש עם 2 states: "Idle" (מנגן idle) ו-"Hover" (מנגן hover)
  6. הוסיפו Boolean input בשם "isHovering"
  7. צרו transition מ-Idle ל-Hover עם condition "isHovering = true", ו-transition חזרה עם "isHovering = false"
  8. בדקו ב-Preview של Rive — שנו את isHovering ידנית ותראו את המעבר
  9. ייצאו כ-.riv — נשתמש בקובץ בסעיף הבא

קריטריון הצלחה: יש לכם קובץ .riv עם state machine שעובד — מעבר חלק בין idle ל-hover ובחזרה.

3 דקות עשו עכשיו: חקרו Rive Community files
  1. פתחו Rive Community
  2. חפשו "button" — בחרו כפתור אנימטיבי שמוצא חן בעיניכם
  3. לחצו "Open in Rive" — תראו את ה-Editor עם ה-artboard, האנימציות, וה-state machine
  4. לחצו על "State Machine" בתחתית — תראו את המצבים, המעברים, וה-inputs. זה מה שהופך את הכפתור לאינטראקטיבי
בינוני 10 דקות קוד

9.8 שילוב Rive באתר — מ-Canvas עד React

כמו Lottie, גם ל-Rive יש כמה דרכים לשילוב. ההבדל העיקרי: Rive מרנדר ל-Canvas (לא SVG), ולכן הביצועים בדרך כלל טובים יותר — אבל אין גישה ל-DOM elements של האנימציה.

דרך 1: @rive-app/canvas — Vanilla JavaScript

// התקנה: npm install @rive-app/canvas
import { Rive } from '@rive-app/canvas';

// יצירת instance
const rive = new Rive({
  src: '/animations/button.riv',      // URL לקובץ .riv
  canvas: document.getElementById('rive-canvas'), // canvas element
  autoplay: true,
  stateMachines: 'ButtonState',       // שם ה-state machine
  onLoad: () => {
    // ה-.riv נטען — עכשיו אפשר לשלוט ב-inputs
    console.log('Rive loaded!');

    // קבלת ה-inputs
    const inputs = rive.stateMachineInputs('ButtonState');
    console.log(inputs); // [{name: 'isHovered', type: 56}, ...]
  }
});

// HTML:
// <canvas id="rive-canvas" width="300" height="200"></canvas>

דרך 2: Rive Web Component (פשוט יותר)

<!-- טעינת הספרייה -->
<script src="https://unpkg.com/@rive-app/canvas@2"></script>

<!-- שימוש -->
<canvas id="rive-canvas" width="400" height="300"></canvas>

<script>
const rive = new RiveCanvas.Rive({
  src: '/animations/hero-character.riv',
  canvas: document.getElementById('rive-canvas'),
  autoplay: true,
  stateMachines: 'MainState',
  fit: RiveCanvas.Fit.contain,    // contain, cover, fill, fitWidth, fitHeight
  alignment: RiveCanvas.Alignment.center
});
</script>

דרך 3: rive-react — React integration

// התקנה: npm install @rive-app/react-canvas
import { useRive, useStateMachineInput } from '@rive-app/react-canvas';

function AnimatedButton() {
  // useRive — טוען את הקובץ ומחזיר RiveComponent
  const { rive, RiveComponent } = useRive({
    src: '/animations/button.riv',
    stateMachines: 'ButtonState',
    autoplay: true,
  });

  // useStateMachineInput — גישה ל-input ספציפי
  const isHovered = useStateMachineInput(rive, 'ButtonState', 'isHovered');
  const clickTrigger = useStateMachineInput(rive, 'ButtonState', 'click');

  return (
    <div
      onMouseEnter={() => isHovered && (isHovered.value = true)}
      onMouseLeave={() => isHovered && (isHovered.value = false)}
      onClick={() => clickTrigger?.fire()}
      style={{ width: 200, height: 60, cursor: 'pointer' }}
    >
      <RiveComponent />
    </div>
  );
}

// עם מספר inputs
function ProgressIndicator({ progress }) {
  const { rive, RiveComponent } = useRive({
    src: '/animations/progress.riv',
    stateMachines: 'ProgressMachine',
    autoplay: true,
  });

  const progressInput = useStateMachineInput(
    rive, 'ProgressMachine', 'progress'
  );

  // עדכון ה-input כשה-prop משתנה
  useEffect(() => {
    if (progressInput) {
      progressInput.value = progress; // 0-100
    }
  }, [progress, progressInput]);

  return <RiveComponent style={{ width: 300, height: 300 }} />;
}
אזהרה: Canvas accessibility

Rive מרנדר ל-Canvas — וזה אומר שתוכן האנימציה לא נגיש לקוראי מסך. ב-Lottie (SVG renderer), לפחות יש SVG elements שקוראי מסך יכולים לגשת אליהם. עם Rive, אתם חייבים להוסיף: (1) aria-label על ה-canvas element שמתאר את האנימציה, (2) role="img" על ה-canvas, (3) טקסט חלופי ב-HTML שמוסתר ויזואלית אבל נגיש (sr-only). אם האנימציה מכילה תוכן קריטי — שקלו להשתמש ב-Lottie SVG במקום.

5 דקות עשו עכשיו: שלבו Rive בדף
  1. פתחו CodePen חדש
  2. הוסיפו canvas element: <canvas id="rive" width="400" height="400"></canvas>
  3. טענו את Rive runtime מ-CDN (ראו דוגמה למעלה)
  4. חפשו ב-Rive Community אנימציה עם state machine — העתיקו את ה-URL של קובץ .riv
  5. צרו instance של Rive עם src, canvas, autoplay ו-stateMachines
  6. בדקו: האנימציה רצה? ה-state machine מגיב ל-hover/click?
מתקדם 8 דקות קוד

9.9 אינטראקטיביות מתקדמת עם Rive — state machine inputs בזמן ריצה

היופי של Rive הוא שה-state machine עושה את רוב העבודה. אתם רק צריכים "להאכיל" אותו ב-inputs — והוא מחליט לבד מה לנגן. בסעיף הזה נראה דפוסים מתקדמים של חיבור state machine inputs לאינטראקציות משתמש.

דפוס 1: Hover + Click עם Boolean ו-Trigger

const rive = new Rive({
  src: '/animations/interactive-icon.riv',
  canvas: document.getElementById('rive-canvas'),
  stateMachines: 'IconState',
  autoplay: true,
  onLoad: () => {
    const inputs = rive.stateMachineInputs('IconState');

    // מציאת inputs לפי שם
    const isHovered = inputs.find(i => i.name === 'isHovered');
    const clickTrigger = inputs.find(i => i.name === 'click');
    const isActive = inputs.find(i => i.name === 'isActive');

    const canvas = document.getElementById('rive-canvas');

    // Hover
    canvas.addEventListener('mouseenter', () => {
      if (isHovered) isHovered.value = true;
    });
    canvas.addEventListener('mouseleave', () => {
      if (isHovered) isHovered.value = false;
    });

    // Click — toggle active + fire trigger
    canvas.addEventListener('click', () => {
      if (clickTrigger) clickTrigger.fire();
      if (isActive) isActive.value = !isActive.value;
    });
  }
});

דפוס 2: Mouse tracking — העכבר שולט באנימציה

const rive = new Rive({
  src: '/animations/character-eyes.riv',
  canvas: document.getElementById('rive-canvas'),
  stateMachines: 'LookAround',
  autoplay: true,
  onLoad: () => {
    const inputs = rive.stateMachineInputs('LookAround');
    const mouseX = inputs.find(i => i.name === 'mouseX');
    const mouseY = inputs.find(i => i.name === 'mouseY');

    const canvas = document.getElementById('rive-canvas');

    document.addEventListener('mousemove', (e) => {
      if (!mouseX || !mouseY) return;

      // נרמול ל-0-100 ביחס ל-canvas
      const rect = canvas.getBoundingClientRect();
      const x = ((e.clientX - rect.left) / rect.width) * 100;
      const y = ((e.clientY - rect.top) / rect.height) * 100;

      mouseX.value = Math.max(0, Math.min(100, x));
      mouseY.value = Math.max(0, Math.min(100, y));
    });
  }
});

דפוס 3: Scroll-driven Rive — התקדמות לפי גלילה

const rive = new Rive({
  src: '/animations/story.riv',
  canvas: document.getElementById('rive-canvas'),
  stateMachines: 'StoryProgress',
  autoplay: true,
  onLoad: () => {
    const inputs = rive.stateMachineInputs('StoryProgress');
    const progress = inputs.find(i => i.name === 'scrollProgress');

    if (!progress) return;

    window.addEventListener('scroll', () => {
      const scrollPercent = window.scrollY /
        (document.documentElement.scrollHeight - window.innerHeight);
      progress.value = scrollPercent * 100; // 0-100
    }, { passive: true });
  }
});

דפוס 4: Application state → Rive state

// חיבור Rive ל-state של האפליקציה
// למשל: form validation שמשנה את האנימציה

const rive = new Rive({
  src: '/animations/form-feedback.riv',
  canvas: document.getElementById('form-rive'),
  stateMachines: 'FormState',
  autoplay: true,
  onLoad: () => {
    const inputs = rive.stateMachineInputs('FormState');
    const isValid = inputs.find(i => i.name === 'isValid');
    const isError = inputs.find(i => i.name === 'isError');
    const submitTrigger = inputs.find(i => i.name === 'submit');
    const successTrigger = inputs.find(i => i.name === 'success');

    // כשהטופס valid
    document.getElementById('email').addEventListener('input', (e) => {
      const valid = e.target.value.includes('@');
      if (isValid) isValid.value = valid;
      if (isError) isError.value = !valid && e.target.value.length > 0;
    });

    // כשלוחצים submit
    document.getElementById('form').addEventListener('submit', async (e) => {
      e.preventDefault();
      if (submitTrigger) submitTrigger.fire();

      try {
        await sendForm();
        if (successTrigger) successTrigger.fire();
      } catch {
        if (isError) isError.value = true;
      }
    });
  }
});

שימו לב לדפוס: הקוד שלכם פשוט — הוא רק שולח inputs. כל הלוגיקה של "איך נראה success", "איך נראה error", "מה המעבר בין hover ל-click" — מוגדרת ב-state machine של Rive. זה הפרדת אחריות מצוינת: המעצב מגדיר את ה-look & feel, המפתח מגדיר את ה-data flow.

25 דקות תרגיל: בנו אנימציה אינטראקטיבית עם Rive
  1. חפשו ב-Rive Community אנימציה עם state machine שכולל לפחות 2 inputs (hover + click, או boolean + trigger)
  2. שלבו אותה בדף HTML (CodePen או מקומי) עם @rive-app/canvas
  3. חברו hover (mouseenter/mouseleave) ל-Boolean input
  4. חברו click ל-Trigger input
  5. בדקו: hover מפעיל מעבר חלק? click מפעיל אנימציה חד-פעמית? המעבר חזרה ל-idle חלק?
  6. בונוס: הוסיפו scroll-driven input — מספר שמתעדכן לפי מיקום הגלילה

קריטריון הצלחה: אנימציית Rive בדף שלכם מגיבה ל-hover ו-click — עם מעברים חלקים שה-state machine מנהל.

מתחיל 6 דקות החלטה

9.10 Lottie מול Rive — framework החלטה

אחרי שלמדתם את שני הכלים, השאלה הגדולה: מתי Lottie ומתי Rive? הנה framework ברור עם 8 קריטריונים:

Framework: Lottie vs Rive — טבלת החלטה
קריטריוןLottieRiveמנצח
שוק אנימציות מוכנות200,000+ ב-LottieFiles. שוק ענק, כל סגנוןאלפים ב-Rive Community. שוק קטן אבל גדלLottie
אינטראקטיביותבסיסית — play, pause, segments. צריך JS לכל אינטראקציהState machines מובנים. Hover, click, inputs — בלי JSRive
גודל קובץJSON: 5-200KB. dotlottie: 1-50KB.riv: 2-50KB (בינארי, דחוס)Rive (קטן יותר)
גודל Runtimelottie-web: ~250KB. lottie-light: ~150KB@rive-app/canvas: ~150KBשווה
RendererSVG (ברירת מחדל), Canvas, HTMLCanvas בלבד (WebGL אופציונלי)Lottie (SVG = DOM access)
Learning curveנמוכה — script tag + web componentבינונית — צריך להבין state machinesLottie
כלי יצירהAfter Effects + Bodymovin (מקצועי, יקר)Rive Editor (חינם, בדפדפן)Rive (נגישות)
React integration@lottiefiles/react-lottie-player — עובד@rive-app/react-canvas + useStateMachineInput — מצויןRive
Framework: כלל ההחלטה המהיר
המצב שלכםבחרולמה
צריכים loading/success/error animation מהרLottieשוק ענק, מוצאים ב-30 שניות, שורת קוד אחת
צריכים אייקון/איור אנימטיבי ללא אינטראקציהLottiePlay and forget — פשוט ויעיל
צריכים כפתור/toggle עם hover+click statesRiveState machine מנהל מעברים — קוד נקי
צריכים דמות/avatar שמגיבה למשתמשRiveMouse tracking, bones, blend states
צריכים אנימציה שמגיבה ל-app stateRiveNumber/Boolean inputs מחוברים ל-state machine
צריכים SVG animation שקוראי מסך יכולים לגשת אליהLottieSVG renderer = DOM elements נגישים
צריכים ביצועים מקסימליים עם הרבה אנימציותRiveCanvas renderer + קבצים קטנים יותר
לא יודעים — ורוצים להתחיל מהרLottieLearning curve נמוכה, שוק ענק, documentation מצוין
2 דקות עשו עכשיו: החליטו על הפרויקט שלכם
  1. חשבו על הפרויקט האחרון שבניתם (או על הפרויקט שרצתם לבנות)
  2. כתבו 3 מקומות בפרויקט שבהם תשלבו אנימציה — ולכל אחד, החליטו: Lottie או Rive?
  3. השתמשו בטבלה למעלה כדי לנמק את הבחירה
בינוני 8 דקות ביצועים

9.11 גודל קבצים וביצועים — JSON מול .riv, lazy loading ו-Intersection Observer

אנימציות מוכנות חינמיות מבחינת זמן פיתוח — אבל לא חינמיות מבחינת ביצועים. כל אנימציה זה קובץ שנטען + ספרייה שמרנדרת. בסעיף הזה נלמד איך לשמור על ביצועים מעולים.

מפת גדלים — מה שוקל כמה:

// גודל Runtime (חד-פעמי — נטען פעם אחת)
lottie-web (full):        ~250KB (gzipped: ~75KB)
lottie-web (light):       ~150KB (gzipped: ~45KB)
@rive-app/canvas:         ~150KB (gzipped: ~50KB)
@dotlottie/player:        ~100KB (gzipped: ~35KB)

// גודל קבצים (לכל אנימציה)
Lottie JSON (פשוט):      5-30KB   → gzipped: 2-10KB
Lottie JSON (מורכב):     50-200KB → gzipped: 15-60KB
dotlottie (.lottie):      1-50KB  (כבר דחוס)
Rive (.riv):              2-50KB  (בינארי, כבר דחוס)
GIF (אותה אנימציה):      500KB-5MB (!!!)
MP4 (אותה אנימציה):      200KB-2MB

// לשם השוואה:
תמונת JPEG ממוצעת:       50-200KB
פונט web (woff2):         20-50KB

Lazy loading עם Intersection Observer — הדפוס הזהב:

אם יש אנימציות Lottie או Rive שלא נראות ב-viewport הראשוני — אל תטענו אותן מראש. Intersection Observer מאפשר לטעון את הספרייה + הקובץ רק כשהמשתמש גולל אליהם:

// Lazy loading של Lottie — טעינה רק כשנראה
function lazyLoadLottie(selector) {
  const elements = document.querySelectorAll(selector);

  const observer = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        const el = entry.target;
        const src = el.dataset.src; // data-src במקום src

        // טעינת lottie-player dynamically (אם לא נטען כבר)
        if (!customElements.get('lottie-player')) {
          const script = document.createElement('script');
          script.src = 'https://unpkg.com/@lottiefiles/lottie-player@2/dist/lottie-player.js';
          document.head.appendChild(script);
          script.onload = () => el.setAttribute('src', src);
        } else {
          el.setAttribute('src', src);
        }

        observer.unobserve(el);
      }
    });
  }, {
    rootMargin: '200px' // טוען 200px לפני שנכנס ל-viewport
  });

  elements.forEach(el => observer.observe(el));
}

// HTML:
// <lottie-player data-src="/animations/feature.json"
//   style="width:300px; height:300px;"
//   loop autoplay>
// </lottie-player>

// JavaScript:
lazyLoadLottie('lottie-player[data-src]');
// Lazy loading של Rive
function lazyLoadRive(canvasId, rivSrc, stateMachine) {
  const canvas = document.getElementById(canvasId);

  const observer = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        // טעינה דינמית של Rive runtime
        import('@rive-app/canvas').then(({ Rive }) => {
          new Rive({
            src: rivSrc,
            canvas: canvas,
            autoplay: true,
            stateMachines: stateMachine,
          });
        });
        observer.unobserve(canvas);
      }
    });
  }, { rootMargin: '100px' });

  observer.observe(canvas);
}

Best practices לביצועים:

// עצירת אנימציות שלא נראות — חיסכון CPU
const players = document.querySelectorAll('lottie-player');

const visibilityObserver = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    const player = entry.target;
    if (entry.isIntersecting) {
      player.play();
    } else {
      player.pause(); // עוצר כשלא נראה — חוסך CPU
    }
  });
}, { threshold: 0 });

players.forEach(p => visibilityObserver.observe(p));
אזהרה: Mobile performance — זהירות מיוחדת

מכשירי mobile עם מעבדים חלשים יותר מושפעים במיוחד מאנימציות Lottie/Rive. שלושה כללים: (1) מקסימום 2 אנימציות בו-זמנית ב-mobile. (2) השתמשו ב-lottie-light במקום lottie-web — חוסך 100KB. (3) בדקו ב-Chrome DevTools > Performance > CPU throttling 4x — אם האנימציה לא חלקה ב-4x throttling, היא לא תהיה חלקה במכשירים ישנים.

מתחיל 6 דקות AI

9.12 חמישה פרומפטים AI ל-Lottie ו-Rive

כלי AI כמו Bolt, Lovable, Cursor ו-Claude מכירים גם Lottie וגם Rive — אבל כמו תמיד, איכות הפרומפט קובעת. הנה 5 פרומפטים שעובדים:

פרומפט 1: Lottie integration בסיסי

"Add a Lottie animation to the hero section.
Use the lottie-player web component from @lottiefiles/lottie-player.
Animation source: [URL from LottieFiles].
Requirements:
- Size: 400x400px, centered
- Background: transparent
- Autoplay with loop
- Speed: 0.8 (slightly slower than default)
- Lazy load: only load when visible (Intersection Observer)
- Add aria-label describing the animation for accessibility"

פרומפט 2: Lottie scroll-driven

"Create a scroll-driven Lottie animation for the features section.
Use lottie-web directly (not web component) for frame-level control.
Animation source: [URL].
Requirements:
- The animation progress should be tied to scroll position
- When the section enters viewport (top 80%), animation starts at frame 0
- When the section leaves viewport (top 20%), animation is at the last frame
- Use requestAnimationFrame for smooth performance
- Use passive scroll listener
- On mobile: fall back to simple autoplay (no scroll-driven)"

פרומפט 3: Lottie hover segments

"Create a set of 4 feature cards, each with a Lottie icon animation.
Each card has:
- A Lottie animation (different for each card)
- On hover: play frames 0-30 (entrance animation)
- On mouse leave: play frames 30-60 (exit animation)
- Use lottie-web with playSegments for frame control
- Cards layout: CSS Grid, 2x2 on desktop, 1 column on mobile
- Ensure animations don't interfere with each other
- Pause animations that are not visible (Intersection Observer)"

פרומפט 4: Rive interactive button

"Create an interactive submit button using Rive.
Rive file: [URL to .riv file].
State machine name: 'ButtonState'.
Inputs: isHovered (Boolean), click (Trigger), isLoading (Boolean), isSuccess (Boolean).
Requirements:
- Hover: set isHovered to true on mouseenter, false on mouseleave
- Click: fire 'click' trigger, then set isLoading to true
- After 2 seconds: set isLoading to false, isSuccess to true
- Use @rive-app/canvas for vanilla JS (or @rive-app/react-canvas for React)
- Canvas size: 200x60px
- Add aria-label='Submit button' and role='img' for accessibility
- Cursor: pointer on hover"

פרומפט 5: Lottie + Rive combined

"Build a landing page section with both Lottie and Rive animations.
Layout: two columns — left side content, right side animations.

Left column:
- Heading with a small Lottie icon (32x32px) next to it — animated checkmark, autoplay loop
- 3 feature bullets, each with a different Lottie icon that plays on scroll (Intersection Observer)

Right column:
- Large Rive animation (400x400px) of an interactive character
- State machine: 'CharacterState'
- The character follows the mouse (Number inputs: mouseX, mouseY)
- Click triggers a wave animation (Trigger input: 'wave')

Performance:
- Lazy load Rive (it's below the fold on mobile)
- Use lottie-light for the small icons
- Pause all animations when tab is not visible (document.visibilitychange)
- Test with Chrome DevTools Performance panel — target 60fps"
5 דקות עשו עכשיו: הריצו פרומפט AI
  1. בחרו את פרומפט 1 או 4 (הפשוטים יותר)
  2. מצאו URL של אנימציה מתאימה (LottieFiles או Rive Community) והחליפו את ה-[URL]
  3. הריצו את הפרומפט ב-Bolt, Lovable, Cursor או Claude
  4. בדקו: האנימציה עובדת? האינטראקטיביות נכונה? הביצועים סבירים?
  5. אם משהו לא עובד — הוסיפו לפרומפט: "The animation is not [problem]. Fix by [specific solution]"
בינוני 10 דקות תבנית

9.13 תבניות מקצועיות — onboarding, empty states, feedback ו-loading

אנימציות Lottie ו-Rive לא צריכות להיות "decoration" — הן יכולות לפתור בעיות UX אמיתיות. בסעיף הזה נראה 4 תבניות מקצועיות שכל אפליקציה מודרנית צריכה, עם קוד מוכן.

תבנית 1: Onboarding animation — מסע קבלת פנים

Onboarding טוב מסביר את המוצר בלי טקסט ארוך. אנימציות Lottie מצוינות לזה — כל שלב ב-onboarding מלווה באנימציה שמסבירה את הפיצ'ר:

<!-- Onboarding: 3 שלבים עם Lottie -->
<div class="onboarding">
  <div class="step active" data-step="1">
    <lottie-player
      src="/animations/onboarding-step1.json"
      style="width: 300px; height: 300px;"
      loop autoplay
    ></lottie-player>
    <h3>ברוכים הבאים!</h3>
    <p>הנה מה שתוכלו לעשות...</p>
  </div>

  <div class="step" data-step="2">
    <lottie-player
      data-src="/animations/onboarding-step2.json"
      style="width: 300px; height: 300px;"
      loop
    ></lottie-player>
    <h3>התאימו אישית</h3>
    <p>בחרו את ההגדרות שמתאימות לכם...</p>
  </div>

  <div class="step" data-step="3">
    <lottie-player
      data-src="/animations/onboarding-step3.json"
      style="width: 300px; height: 300px;"
    ></lottie-player>
    <h3>מוכנים!</h3>
    <p>הכל מוכן — בואו נתחיל</p>
  </div>

  <div class="onboarding-nav">
    <button class="prev" disabled>הקודם</button>
    <div class="dots">
      <span class="dot active"></span>
      <span class="dot"></span>
      <span class="dot"></span>
    </div>
    <button class="next">הבא</button>
  </div>
</div>

<script>
// ניווט בין שלבים — עם lazy loading של אנימציות
let currentStep = 1;
const steps = document.querySelectorAll('.step');

function showStep(n) {
  steps.forEach(s => s.classList.remove('active'));
  const step = document.querySelector(`[data-step="${n}"]`);
  step.classList.add('active');

  // Lazy load: טען אנימציה רק כשנכנסים לשלב
  const player = step.querySelector('lottie-player');
  if (player.dataset.src && !player.getAttribute('src')) {
    player.setAttribute('src', player.dataset.src);
    player.setAttribute('autoplay', '');
  }
  // עצור אנימציות בשלבים אחרים
  steps.forEach(s => {
    if (s !== step) {
      const p = s.querySelector('lottie-player');
      if (p) p.pause();
    }
  });
}

document.querySelector('.next').addEventListener('click', () => {
  if (currentStep < 3) showStep(++currentStep);
});
document.querySelector('.prev').addEventListener('click', () => {
  if (currentStep > 1) showStep(--currentStep);
});
</script>

תבנית 2: Empty state — כשאין תוכן להציג

Empty state הוא מה שהמשתמש רואה כשאין תוכן — רשימה ריקה, חיפוש ללא תוצאות, inbox ריק. אנימציית Lottie הופכת רגע מתסכל לרגע נעים:

<!-- Empty state עם Lottie -->
<div class="empty-state">
  <lottie-player
    src="/animations/empty-search.json"
    style="width: 250px; height: 250px; margin: 0 auto;"
    loop
    autoplay
    speed="0.7"
  ></lottie-player>
  <h3>לא מצאנו תוצאות</h3>
  <p>נסו לחפש עם מילים אחרות, או בדקו את האיות</p>
  <button class="btn-secondary">נקו את החיפוש</button>
</div>

<style>
.empty-state {
  text-align: center;
  padding: 3rem 1rem;
  max-width: 400px;
  margin: 0 auto;
}
.empty-state h3 {
  margin-top: 1rem;
  font-size: 1.25rem;
  color: #333;
}
.empty-state p {
  color: #666;
  margin: 0.5rem 0 1.5rem;
}
</style>

תבנית 3: Success / Error feedback — משוב מיידי

<!-- Success/Error feedback עם Lottie -->
<script>
// פונקציה כללית להצגת feedback
function showFeedback(type) {
  const overlay = document.createElement('div');
  overlay.className = 'feedback-overlay';
  overlay.innerHTML = `
    <lottie-player
      src="/animations/${type === 'success' ? 'success-check' : 'error-x'}.json"
      style="width: 150px; height: 150px;"
      autoplay
    ></lottie-player>
    <p>${type === 'success' ? 'הפעולה הצליחה!' : 'משהו השתבש. נסו שוב.'}</p>
  `;

  document.body.appendChild(overlay);

  // האנימציה רצה פעם אחת (בלי loop) ואז נעלם
  const player = overlay.querySelector('lottie-player');
  player.addEventListener('complete', () => {
    setTimeout(() => {
      overlay.classList.add('fade-out');
      overlay.addEventListener('animationend', () => overlay.remove());
    }, 800);
  });
}

// שימוש:
// showFeedback('success');
// showFeedback('error');
</script>

<style>
.feedback-overlay {
  position: fixed;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: rgba(255,255,255,0.95);
  z-index: 1000;
  animation: fadeIn 0.3s ease;
}
.feedback-overlay p {
  font-size: 1.2rem;
  margin-top: 1rem;
  font-weight: 600;
}
.feedback-overlay.fade-out {
  animation: fadeOut 0.3s ease forwards;
}
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } }
</style>

תבנית 4: Loading indicator — טעינה חכמה עם Rive

<!-- Loading indicator אינטראקטיבי עם Rive -->
<!-- ה-state machine מגיב ל-progress input -->
<canvas id="loading-canvas" width="200" height="200"
  aria-label="מחוון טעינה" role="img"></canvas>

<script>
let loadingRive;

async function initLoadingIndicator() {
  const { Rive } = await import('@rive-app/canvas');

  loadingRive = new Rive({
    src: '/animations/loading-indicator.riv',
    canvas: document.getElementById('loading-canvas'),
    stateMachines: 'LoadingState',
    autoplay: true,
    onLoad: () => {
      console.log('Loading indicator ready');
    }
  });
}

// עדכון progress (0-100)
function updateLoadingProgress(percent) {
  if (!loadingRive) return;
  const inputs = loadingRive.stateMachineInputs('LoadingState');
  const progress = inputs.find(i => i.name === 'progress');
  if (progress) progress.value = percent;
}

// הצגת הצלחה
function showLoadingSuccess() {
  if (!loadingRive) return;
  const inputs = loadingRive.stateMachineInputs('LoadingState');
  const success = inputs.find(i => i.name === 'success');
  if (success) success.fire();
}

// שימוש בתהליך טעינה אמיתי:
async function fetchData() {
  initLoadingIndicator();

  const response = await fetch('/api/data');
  const reader = response.body.getReader();
  const total = parseInt(response.headers.get('content-length'));
  let loaded = 0;

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    loaded += value.length;
    updateLoadingProgress((loaded / total) * 100);
  }

  showLoadingSuccess();
}
</script>
20 דקות תרגיל: בנו empty state ו-success feedback
  1. חפשו ב-LottieFiles: "empty" או "no results" — בחרו אנימציה שמתאימה לאפליקציה שלכם
  2. חפשו גם: "success check" — בחרו אנימציית success
  3. בנו דף עם שני מצבים: (א) empty state עם אנימציה וטקסט (ב) כפתור "הוסף פריט" שכשלוחצים — מציג success animation
  4. ה-empty state: Lottie בלופ, מהירות 0.7, 250x250
  5. ה-success: Lottie בלי לופ, מנגן פעם אחת, ואז נעלם (fadeOut)
  6. בונוס: הוסיפו error animation לכפתור שני

קריטריון הצלחה: שני מצבים עובדים — empty state עם אנימציה בלופ, ו-success animation שרצה פעם אחת ונעלמת.

עוד תבניות מקצועיות שכדאי להכיר:

המפתח: אנימציה מוכנה צריכה לפתור בעיה, לא "לקשט". Empty state בלי אנימציה = המשתמש חושב שמשהו שבור. Success animation בלי feedback = המשתמש לא בטוח שהפעולה הצליחה. Loading animation = המשתמש יודע שמשהו קורה ולא עוזב. כל אנימציה שאתם מוסיפים צריכה לענות על "למה זה פה?" — אם אין תשובה טובה, אל תוסיפו.

צ'קליסט — לפני שמפרסמים אנימציות Lottie / Rive
שגרת עבודה: שילוב אנימציות מוכנות
שלבפעולהזמן
1. זיהויזהו 3-5 מקומות בפרויקט שצריכים אנימציה (loading, empty, success, onboarding, interaction). לכל מקום: Lottie או Rive?10 דקות
2. חיפושחפשו ב-LottieFiles / Rive Community. בחרו 2-3 אופציות לכל מקום. בדקו רישיון, גודל קובץ, וסגנון15 דקות
3. התאמההתאימו צבעים ומהירות ב-LottieFiles Editor. ב-Rive — בדקו שה-state machine מכסה את כל ה-states שצריך10 דקות
4. שילובשלבו בקוד — lottie-player לפשוט, lottie-web לשליטה, @rive-app/canvas ל-Rive. חברו inputs20 דקות
5. Performanceהוסיפו lazy loading, pause on invisible, preload לקריטיים. בדקו גודלי קבצים10 דקות
6. A11yaria-labels, role="img", prefers-reduced-motion. בדקו עם קורא מסך10 דקות
7. Testבדקו ב-mobile (CPU throttling), בדקו responsive, בדקו edge cases (empty, error, slow network)15 דקות
בדקו את עצמכם — מה למדתם בפרק
סיכום הפרק
מה בפרק הבא

בפרק הזה למדתם Lottie ו-Rive — אנימציות מוכנות שמעלות את הרמה בזמן מינימלי. אבל יש סוגי אנימציות שגם Lottie, גם Rive, וגם SVG לא יכולים לעשות: particles, generative art, data visualization מורכב, ואפקטים פיקסליים. בפרק 10 תלמדו Canvas API — ציור פיקסלי בדפדפן. תלמדו את ה-API הבסיסי (shapes, paths, colors), אנימציה עם requestAnimationFrame, particles systems, ואיך לשלב Canvas עם GSAP. Canvas הוא הכלי האחרון בארגז — ואיתו תוכלו לבנות כל דבר.

→ פרק קודם: SVG — גרפיקה וקטורית | פרק הבא: Canvas ←