מערכת חלקיקים אחת, ארבע נשמות. מדריך מלא: הארכיטקטורה, האלגוריתמים, קטעי הקוד המרכזיים — ואיך לשחזר את זה בעצמכם.
הרעיון: רגש הוא לא צבע — רגש הוא תנועה. שמחה מבעבעת מעלה, געגוע נמשך אל נקודה רחוקה שלעולם לא מגיעים אליה, כעס רועד ומתפרץ, ושלווה נושמת בגלים. לכן במקום ארבע סצנות נפרדות, בנינו מערכת חלקיקים אחת שכל "רגש" בה הוא סט של כוחות פיזיקליים, פלטת צבע, קצב דעיכה — ואוצר מילים עברי שצף בתוך השדה.
הסמן הוא המבקר בשדה: בשמחה החלקיקים רוקדים סביבו, בגעגוע הם נשענים לעברו, בכעס הם נהדפים ממנו בכוח, ובשלווה הם זזים הצידה ברוך ומפנים לו מקום. לחיצה מולידה התפרצות — ומילה.
ציפה כלפי מעלה עם נדנוד סינוסי שובב. הסמן יוצר מערבולת קונפטי סביבו.
אור · צחוק · ריקוד · ניצוץ · דבש
משיכה איטית אל "מגדלור" נודד שאיש לא מגיע אליו, עם שקיעה עדינה מטה.
מרחק · זיכרון · בית · פעם · עוד רגע
רעד אקראי אלים עם התפרצויות כיוון פתאומיות. הסמן הודף בכוח ריבועי.
אש · סערה · גבול · די · רעם
שדה זרימה סינוסי נושם, דעיכה גבוהה — תנועה איטית שלא נעצרת לעולם.
נשימה · שקט · ים · רוך · כאן
| רגש | כוח מרכזי | דעיכה (damping) | סמן |
|---|---|---|---|
| שמחה | ציפה + נדנוד | 0.965 | מערבולת משיקית |
| געגוע | משיכה למגדלור | 0.985 | משיכה עדינה |
| כעס | רעש אקראי חזק | 0.930 | הדיפה ריבועית |
| שלווה | שדה זרימה | 0.988 | גל עדין |
כל התנהגות היא פונקציה טהורה שמקבלת חלקיק וזמן ומחזירה וקטור כוח [fx, fy]. זה כל ההבדל בין הרגשות — ארבע פונקציות קטנות:
const behaviors = { joy(p, t){ // ציפה מעלה + נדנוד שובב const fx = Math.sin(p.phase + t*p.freq*2.2) * .045; const fy = -.052 - Math.sin(t*.8 + p.phase) * .012; return [fx, fy]; }, longing(p, t){ // משיכה אל מגדלור שלא מגיעים אליו const dx = beacon.x - p.x, dy = beacon.y - p.y; const d = Math.hypot(dx, dy) + 40; const pull = 2.4 / d; // נחלש עם המרחק — לכן לא מגיעים return [dx/d*pull, dy/d*pull + .012]; }, anger(p, t){ // רעד + התפרצויות let fx = (Math.random()-.5)*.38, fy = (Math.random()-.5)*.38; if (Math.random() < .012) { fx *= 9; fy *= 9; } return [fx, fy]; }, calm(p, t){ // שדה זרימה נושם const k = .0038; return [Math.sin(p.y*k + t*.35)*.02, Math.cos(p.x*k + t*.3)*.014]; }, };
pull = 2.4/d), כך שהחלקיקים תמיד נעים אל האור אבל לעולם לא מגיעים אליו. פיזיקה קטנה שמייצרת מטאפורה שלמה.כשמחליפים רגש לא "מאפסים" את הסצנה. שני הרגשות רצים במקביל במשך 2.2 שניות, וכל חלקיק מרגיש שילוב לינארי של שני הכוחות לפי מקדם mix שעובר easing קובי:
const ease = t => t < 0.5 ? 4*t*t*t : 1 - Math.pow(-2*t+2, 3)/2; const m = ease(mix); // 0 = הרגש הקודם, 1 = הנוכחי const fA = behaviors[previous](p, T); const fB = behaviors[current](p, T); p.vx += lerp(fA[0], fB[0], m); p.vy += lerp(fA[1], fB[1], m); // גם הצבעים, הרקע והדעיכה עוברים lerp באותו מקדם
התוצאה: כעס "נרגע" בהדרגה לתוך שלווה, שמחה "שוקעת" לתוך געגוע. המעבר עצמו הוא חלק מהסיפור הרגשי.
במקום לנקות את הקנבס, מציירים כל פריים מלבן של צבע הרקע ב־16% אטימות. מה שצויר קודם דוהה בהדרגה — וכל חלקיק מקבל שובל חינם:
ctx.fillStyle = `rgba(${bg[0]},${bg[1]},${bg[2]}, 0.16)`; ctx.fillRect(0, 0, W, H); // ואז החלקיקים מצוירים ב-'lighter' — אור שמצטבר ctx.globalCompositeOperation = 'lighter';
כל רגש מחזיק אוצר מילים משלו. מילה נולדת כל 2.6–4.6 שניות (או בלחיצה), מרחפת עם השדה ודוהה בעקומת sin(k·π) — נכנסת ויוצאת ברכות. הפונט: Frank Ruhl Libre במשקל 300, ישירות על הקנבס.
בגרסה המורחבת השדה הפך מ"דמו במסך אחד" לאתר אמיתי — בלי לוותר על הקונספט. הקנבס נשאר רקע חי וקבוע (position:fixed) שממשיך לנשום מאחורי כל העמוד, והתוכן נגלל מעליו על פאנלים שקופים־למחצה עם backdrop-filter: blur.
text-shadow בצבע הרגש. בהחלפה היא יוצאת ב־blur, מתחלפת, ונכנסת מחדש.scrollY, כך שהשדה בוהק בהירו ומתעמעם מאחורי התוכן.IntersectionObserver מקפיא מיני־שדות שמחוץ למסך.fromTo(y:44, opacity:0 → 1) על כל [data-reveal], פעם אחת לכל אלמנט, ומוני מספרים בסקשן "על הפרויקט".scrub:true.opacity:0 (לפני אנימציית הכניסה של ה־CSS) — והמילה נעלמה לגמרי. הפתרון: עוטפים אותה ב־wrapper, הכניסה רצה על הפנימי, הפרלקסה על העוטף, עם fromTo(..., immediateRender:false).ולמה אין כאן אף תמונת AI? שקלנו — והחלטנו נגד. הקונספט של האתר הוא "רגש מתנועה בלבד": כל פיקסל מיוצר פרוצדורלית בזמן אמת. תמונה סטטית הייתה שוברת בדיוק את הטענה שהאתר מוכיח. אפס תמונות זה פיצ'ר.
devicePixelRatio מוגבל ל־2; ספירת חלקיקים: 700 בדסקטופ, 320 במובייל, ועוד 46 לכל מיני־שדה בכרטיסים (רק כשהם על המסך).shadowBlur היקר.dt אמיתי (clamp ל־50ms) — מהירות זהה בכל קצב פריימים.prefers-reduced-motion: מהירות ×0.45, פחות חלקיקים, דהייה מהירה של שובל, כמעט ללא אנימציות CSS.focus-visible.document.fonts.load), ואז כוריאוגרפיית כניסה מדורגת — שורת פתיחה, כותרת, מילת הרגש, תיאור, מחליף הרגשות, ניווט עליון.scrollY < 70% מגובה החלון) — לא מפריעות לקריאה בהמשך העמוד.אין תלות בשום ספרייה — הכול Canvas 2D ונקודות. המתכון:
ctx דו־ממדי.boost שדועך ב־0.82 לפריים) + מילה.כל הקוד גלוי בקובץ index.html של העמוד הראשי — בלי בנייה, בלי מודולים. העתיקו, שנו את הכוחות, המציאו רגש חמישי.