האטה שמבוססת על פיזיקה

תכונות אינטרנט: פונקציית התנועה linear()‎

פונקציות ריכוך מסורתיות של CSS כמו ease-in או cubic-bezier() מוגבלות לעקומות פשוטות, ולכן אי אפשר ליצור אפקטים מורכבים שמבוססים על פיזיקה, כמו קפיצות או קפיצים. פונקציית התזמון linear() פותרת את הבעיה הזו בכך שהיא מאפשרת לכם לספק סדרה של נקודות עצירה שיכולות להעריך עקומות מורכבות. המעברים והאנימציות מחושבים על סמך קווים ישרים בין נקודות העצירה, אבל אם יש מספיק נקודות עצירה, המעבר יכול להיראות חלק.

שלבי ההטמעה

  1. יצירת נקודות העצירה של העקומה: לא מעשי לשרטט ידנית עשרות נקודות בשביל קפיצה או ניתור. אפשר להשתמש בפונקציית תזמון מספרייה חיצונית, או להשתמש בכלי כדי להמיר פונקציית האטה קיימת של JavaScript או נתיב SVG לתחביר linear(). אופציונלי: אפשר לשמור את פונקציות התזמון האלה כמאפיינים מותאמים אישית של CSS כדי להשתמש בהן שוב באתר.
  2. הגדרת פונקציית התזמון: מחילים את נקודות העצירה שנוצרו על המאפיין transition-timing-function או animation-timing-function, או באמצעות קיצורי הדרך transition או animation.
  3. התאמת משך הזמן: בניגוד למנועי פיזיקה של JavaScript שבהם משך הזמן נגזר ממאפיינים פיזיים (מסה, קשיחות), ב-CSS עדיין נדרש duration קבוע. יכול להיות שתצטרכו לשנות את משך הזמן כדי לקבל את האפקט הרצוי.

דוגמה: Spring Easing

הדוגמה הזו מראה איך להשתמש בפונקציה linear() מותאמת אישית כדי ליצור אפקט קפיצי שחורג מערך היעד לפני שהוא מתייצב.

.spring {
  /* Define the physics-based easing as a reusable variable */
  --spring-easing: linear(0, 0.016 0.5%, 0.06 1%, 0.226 2%, 1.116 5.4%, 1.375 6.6%, 1.527 7.7%, 1.565 8.2%, 1.585 8.8%, 1.581 9.3%, 1.559 9.8%, 1.458 10.9%, 0.937 14.3%, 0.784 15.5%, 0.693 16.6%, 0.67 17.1%, 0.657 17.7%, 0.671 18.7%, 0.729 19.8%, 1.042 23.3%, 1.13 24.5%, 1.182 25.6%, 1.201 26.7%, 1.192 27.7%, 1.156 28.8%, 0.977 32.2%, 0.925 33.4%, 0.894 34.5%, 0.882 35.6%, 0.887 36.6%, 0.907 37.7%, 1.045 42.4%, 1.069 44.5%, 1.059 46.3%, 0.979 50.9%, 0.96 53.4%, 0.966 55.3%, 1.013 59.9%, 1.024 62.3%, 0.986 71.2%, 1.008 79.9%, 0.995 88.9%, 1);


  /* Apply the easing with a duration that fits the spring's complexity */
  /* MANDATORY: Always include a duration; linear() does not calculate it automatically */
  transition: scale 0.8s var(--spring-easing);
}

.spring:hover {
  scale: 1.2;
}

דוגמה: Bounce Easing

בדוגמה הזו אפשר לראות איך משתמשים בפונקציה linear() בהתאמה אישית כדי ליצור אפקט של קפיצה.

.bounce {
  /* Define the physics-based easing as a reusable variable */
  --bounce-easing: linear(0, 0.214 14.7%, 0.386 23.7%, 0.598 31.9%, 0.999 44.7%, 0.807 52.6%, 0.762 56%, 0.747 59.4%, 0.758 62.4%, 0.793 65.6%, 0.999 77.4%, 0.961 81.2%, 0.949 84.8%, 0.956 88%, 0.993 95.5%, 1);


  /* Apply the easing with a duration that fits the bounce's complexity */
  /* MANDATORY: Always include a duration; linear() does not calculate it automatically */
  transition: scale 0.4s var(--bounce-easing);
}

.bounce:hover {
  scale: 1.2;
}

נקודות מרכזיות

  • ביצועים: כדי שהאנימציות שמבוססות על פיזיקה יפעלו בצורה חלקה, כדאי להחיל את linear() על מאפיינים שפועלים בשרשור נפרד, כמו transform ו-opacity.
  • דיוק לעומת עומס: ככל שיש יותר נקודות עצירה, העקומה חלקה יותר, אבל גם גודל ה-CSS גדל. רוב הכלים ליצירת קוד מאפשרים "לפשט" את העקומה כדי למצוא את האיזון האופטימלי בין החלקת הקווים לבין גודל הקוד.
  • הימנעו משימוש באטימות להקפצות: החלת הקלות הקפצה על opacity עלולה לגרום להבהובים צורמים מבחינה חזותית אם הערך חורג מתחת ל-0 או מעל ל-1.
  • נגישות: אנימציות מורכבות שמבוססות על פיזיקה יכולות להסיח את הדעת או לגרום לרגישות לתנועה אצל חלק מהמשתמשים. חשוב לכבד את העדפות המשתמשים ולהפחית או להשבית את האנימציות האלה.
@media (prefers-reduced-motion: reduce) {
  .element {
    transition: none;
  }
}

אסטרטגיות חלופיות

גיבוי של CSS

בדפדפנים שלא תומכים ב-linear(), צריך לספק פונקציית easing רגילה כחלופה. הדפדפן יתעלם מהערך linear() אם הוא לא יזהה אותו, ויחזור להצהרה התקפה הקודמת.

.element {
  /* Fallback for older browsers (standard smooth exit) */
  transition: transform 0.8s ease-out;
  
  /* Modern browsers will override with the physics-based easing */
  transition-timing-function: linear(0, 1.1, 0.95, 1.02, 1);
}

חלופה לספריית JavaScript‏ (Motion/GSAP)

אופציונלי: אם אנימציה פיזיקלית באיכות גבוהה היא קריטית גם בדפדפנים ישנים יותר, אפשר להשתמש בספריית JavaScript כמו Motion‏ (motion.dev) או GSAP‏ (greensock.com) כדי לטפל באנימציה כשאין תמיכה ב-linear().

  1. זיהוי תמיכה: משתמשים ב-CSS.supports() כדי לבדוק אם הדפדפן מטפל בפונקציה linear().
  2. טעינה או החלה מותנית: אם אין תמיכה, משתמשים בהטמעה של קפיץ או הקפצה של הספרייה.
/* Detect if the browser supports the linear() function */
const supportsLinearEasing = window.CSS && CSS.supports('animation-timing-function', 'linear(0, 1)');

if (!supportsLinearEasing) {
  /* 
     Example using Motion (motion.dev) for a spring fallback.
     This should only be initialized if native CSS support is missing.
  */
  import("https://cdn.jsdelivr.net/npm/motion@latest/dist/motion.js").then(({ animate, spring }) => {
    animate(".element", { transform: "scale(1.2)" }, {
      easing: spring({ stiffness: 100, damping: 10 })
    });
  });
}

אפשר גם להשתמש ב-@supports ב-CSS כדי לזהות תכונות באופן מפורש יותר:

@supports not (animation-timing-function: linear(0, 1)) {
  .element {
    /* Alternative experience for unsupported browsers */
    transition-duration: 0.4s;
    transition-timing-function: cubic-bezier(0.34, 1.56, 0.64, 1);
  }
}