אנימציות רספונסיביות לכל גודל מסך ומכשיר PlatoBlockchain Data Intelligence. חיפוש אנכי. איי.

אנימציות רספונסיביות לכל גודל מסך ומכשיר

לפני שקפצתי בקריירה לפיתוח, עשיתי חבורה של עבודות גרפיקה בתנועה באפטר אפקטס. אבל אפילו עם הרקע הזה, עדיין מצאתי את האנימציה באינטרנט די מביכה.

גרפיקת וידאו מעוצבת ביחס מסוים ולאחר מכן מיוצאת החוצה. בוצע! אבל אין "הגדרות ייצוא" באינטרנט. אנחנו פשוט דוחפים את הקוד החוצה אל העולם והאנימציות שלנו צריכות להתאים את עצמנו לכל מכשיר שהן נוחתות עליו.

אז בואו נדבר על אנימציה רספונסיבית! כיצד אנו ניגש בצורה הטובה ביותר להנפשה ברשת הפרועה הפרועה? אנחנו הולכים לכסות כמה גישות כלליות, כמה עצות ספציפיות ל-GSAP וכמה עקרונות תנועה. בואו נתחיל עם קצת מסגור...

כיצד ישמש האנימציה הזו?

המאמר של זאק סוסייר על אנימציה רספונסיבית ממליץ לקחת צעד אחורה כדי לחשוב על התוצאה הסופית לפני קפיצה לקוד.

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

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

רוב האנימציות מתחלקות לקטגוריות הבאות:

  • תוקן: אנימציות לדברים כמו סמלים או מעמיסים ששומרים על אותו גודל ויחס רוחב-גובה בכל המכשירים. אין מה לדאוג כאן! קוד קשיח כמה ערכי פיקסלים שם והמשיכו עם היום שלכם.
  • נוֹזֵל: אנימציות שצריכות להסתגל בצורה זורמת על פני מכשירים שונים. רוב אנימציות הפריסה נכללות בקטגוריה זו.
  • ממוקד: אנימציות ספציפיות למכשיר מסוים או לגודל מסך מסוים, או משתנות באופן מהותי בנקודת עצירה מסוימת, כגון אנימציות לשולחן העבודה בלבד או אינטראקציות שמסתמכות על אינטראקציה ספציפית למכשיר, כמו מגע או ריחוף.

אנימציות נוזליות וממוקדות דורשות דרכי חשיבה ופתרונות שונים. בואו נסתכל…

אנימציה נוזלית

As אנדי בל אומר: היה המנטור של הדפדפן, לא המיקרו-מנהל שלו - תן לדפדפן כמה כללים ורמזים מוצקים, ואז תן לו לקבל את ההחלטות הנכונות עבור האנשים שמבקרים בו. (הנה את השקופיות מהמצגת ההיא.)

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

הקופסה הסגולה אפילו משנה רוחב בנקודות שבירה שונות, אבל כשאנחנו משתמשים באחוזים כדי להזיז אותה, גם האנימציה מתרחבת יחד איתה.

אנימציה מאפייני פריסה כמו left ו top יכול לגרום לזרימות מחדש של פריסה ולהנפשה 'מעצבנת' עצבנית, כך שבמידת האפשר היצמד לטרנספורמציות ואטימות.

עם זאת, אנחנו לא מוגבלים רק ליחידות האלה - בואו נסתכל על כמה אפשרויות אחרות.

יחידות SVG

אחד הדברים שאני אוהב בעבודה עם SVG הוא שאנחנו יכולים להשתמש ביחידות משתמש SVG להנפשה שמגיבות מהקופסה. הרמז נמצא בשם באמת - להרחבה גרפיקה וקטורית. ב-SVG-land, כל האלמנטים משורטטים בקואורדינטות ספציפיות. חלל SVG הוא כמו קטע אינסופי של נייר גרפי שבו אנחנו יכולים לסדר אלמנטים. ה viewBox מגדיר את מידות נייר הגרף שאנו יכולים לראות.

viewBox="0 0 100 50”

בהדגמה הבאה זו, ה-SVG שלנו viewBox is 100 יחידות רחב ו 50 גובה יחידות. זה אומר שאם אנו מניחים את האלמנט על ידי 100 יחידות לאורך ציר ה-x, הוא תמיד ינוע בכל רוחב ה-SVG האב שלו, לא משנה כמה גדול או קטן ה-SVG הזה! תן להדגמה שינוי גודל כדי לראות.

אנימציה של אלמנט צאצא על בסיס רוחב של מיכל אב היא טריק קטן ב-HTML-land. עד עכשיו, היינו צריכים לתפוס את רוחב ההורה עם JavaScript, וזה קל מספיק כשאתה מבצע אנימציה from מיקום שהשתנה, אבל קצת יותר מטורף כשאתה מבצע אנימציה to איפשהו כפי שאתה יכול לראות בהדגמה הבאה. אם נקודת הסיום שלך היא מיקום שעבר שינוי ואתה משנה את גודל המסך, תצטרך להתאים את המיקום הזה באופן ידני. מבולגן... 🤔

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

אבל, חבטת המהירות של האנימציה הזו תהיה בקרוב נחלת העבר! תופים בבקשה... 🥁

יחידות מיכל! דברים מקסימים. בזמן שאני כותב את זה, הם עובדים רק בכרום ובספארי - אבל אולי עד שתקרא את זה, יהיה לנו גם את Firefox. בדוק אותם בפעולה בהדגמה הבאה. תראו את הבחורים הקטנים האלה הולכים! זה לא מרגש, אנימציה יחסית לאלמנטים של ההורים!

נתוני התמיכה בדפדפן זה הם מ אני יכול להשתמש, שיש בו יותר פרטים. מספר מציין שהדפדפן תומך בתכונה בגרסה זו ומעלה.

שולחן העבודה

Chrome Firefox IE אדג ' ספארי
105 לא לא 105 16.0

נייד / טאבלט

אנדרואיד כרום אנדרואיד פיירפוקס אנדרואיד iOS ספארי
106 לא 106 16.0

מעברי פריסה נוזליים עם FLIP

כפי שהזכרנו קודם לכן, ב-SVG-land כל אלמנט ממוקם בצורה מסודרת על רשת אחת וממש קל להזיז אותו בתגובות. ב-HTML-land זה הרבה יותר מורכב. על מנת לבנות פריסות רספונסיביות, אנו עושים שימוש במגוון שיטות מיקום ומערכות פריסה שונות. אחד הקשיים העיקריים של אנימציה באינטרנט הוא זה הרבה בלתי אפשרי להנפשה של שינויים בפריסה. אולי אלמנט צריך לעבור מעמדה relative ל fixed, או שחלק מהילדים של מיכל flex צריכים להיות לערבב בצורה חלקה סביב יציאת התצוגה. אולי אלמנט אפילו צריך להיות הורה מחדש ולהעביר אותו לעמדה חדשה לגמרי ב-DOM.

מסובך, הא?

נו. טכניקת FLIP כאן כדי להציל את היום; זה מאפשר לנו להחיות בקלות את הדברים הבלתי אפשריים האלה. הנחת היסוד היא:

  • ראשון: תפוס את המיקום ההתחלתי של האלמנטים המעורבים במעבר.
  • אחרון: הזיזו את האלמנטים ותפוס את המיקום הסופי.
  • להפוך: חשב את השינויים בין המצב הראשון והאחרון והחל טרנספורמציות כדי להפוך את האלמנטים חזרה למיקומם המקורי. זה גורם לזה להיראות כאילו האלמנטים עדיין נמצאים ב ראשון עמדה אבל הם למעשה לא.
  • לְשַׂחֵק: הסר את הטרנספורמציות ההפוכות והנפיש אותם זייף ראשון המדינה ל אחרון מדינה.

הנה הדגמה באמצעות תוסף FLIP של GSAP שעושה עבורך את כל המשימות הכבדות!

אם אתה רוצה להבין קצת יותר על יישום הווניל, פנה אל פול לואיס בלוג - הוא המוח מאחורי טכניקת ה-FLIP.

קנה מידה נוזלי של SVG

תפסת אותי... זה לא בֶּאֱמֶת טיפ אנימציה. אבל הגדרת הבמה נכונה היא הכרחית לאנימציה טובה! SVG קנה מידה סופר יפה כברירת מחדל, אבל אנחנו יכולים לשלוט כיצד הוא מתרחב עוד יותר עם preserveAspectRatio, וזה מאוד שימושי כאשר יחס הגובה-רוחב של אלמנט SVG וה- viewBox יחס גובה-רוחב שונים. זה עובד הרבה באותו אופן כמו background-position ו background-size נכסים ב-CSS. ההצהרה מורכבת מערך יישור (background-position) ו לִפְגוֹשׁ or פרוסה התייחסות (background-size).

באשר להפניות ל- Meet and Slice - slice הוא כמו background size: cover, ו meet הוא כמו background-size: contain.

  • preserveAspectRatio="MidYMax slice" - יישר לאמצע ציר ה-x, החלק התחתון של ציר ה-Y, והגדל את קנה המידה כדי לכסות את כל יציאת התצוגה.
  • preserveAspectRatio="MinYMin meet" - יישר משמאל לציר ה-x, החלק העליון של ציר ה-Y, והגדלה תוך שמירה על כל viewBox גלוי לעין.

טום מילר לוקח את זה צעד קדימה על ידי שימוש overflow: visible ב-CSS ואלמנט מכיל כדי לחשוף "שלב שמאל" ו"במה ימין" תוך שמירה על הגבלת הגובה:

עבור אנימציות SVG רספונסיביות, זה יכול להיות שימושי להשתמש בתיבת התצוגה של SVG כדי ליצור תצוגה שחותכת ומתרחבת מתחת לרוחב דפדפן מסוים, ובמקביל גם חושפת יותר מהנפשת SVG מימין ומשמאל כאשר הדפדפן רחב מזה. מפתן. נוכל להשיג זאת על ידי הוספת גלישה גלויה ב-SVG ושיתוף פעולה עם א max-height עטיפה כדי למנוע מה-SVG להתאים יותר מדי אנכית.

קנבס בקנה מידה נוזלי

Canvas הוא הרבה יותר ביצועי עבור אנימציות מורכבות עם הרבה של חלקים נעים מאשר הנפשת SVG או HTML DOM, אבל זה גם מורכב יותר מטבעו. אתה צריך לעבוד בשביל ההישגים האלה! בניגוד ל-SVG שיש לו יחידות תגובה מקסימות וקנה מידה מחוץ לקופסה, צריך להתעסק ולנהל קצת במיקרו.

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

ג 'ורג' פרנסיס גם להרכיב את זה ספרייה קטנה ומקסימה המאפשר לך להגדיר קנבס viewBox תכונה ו preserveAspectRatio - בדיוק כמו SVG!

אנימציה ממוקדת

לפעמים אתה צריך לנקוט בגישה פחות זורמת ויותר מכוונת לאנימציה שלך. למכשירים ניידים יש הרבה פחות נדל"ן, ופחות אנימציה-מיץ מבחינת ביצועים ממכונה שולחנית. אז הגיוני להגיש אנימציה מופחתת למשתמשים ניידים, אולי אפילו ללא אנימציה:

לפעמים האנימציה הרספונסיבית הטובה ביותר למובייל היא ללא אנימציה כלל! עבור UX נייד, תעדוף לתת למשתמש לצרוך תוכן במהירות לעומת המתנה לסיום האנימציות. אנימציות ניידות צריכות לשפר את התוכן, הניווט והאינטראקציות במקום לעכב אותם. אריק ואן הולץ

על מנת לעשות זאת, אנו יכולים לעשות שימוש בשאילתות מדיה כדי למקד לגדלי תצוגה ספציפיים בדיוק כפי שאנו עושים כאשר אנו מעצבים עם CSS! הנה הדגמה פשוטה המציגה אנימציית CSS מטופלת באמצעות שאילתות מדיה והנפשת GSAP מטופלת באמצעות gsap.matchMedia():

הפשטות של ההדגמה הזאת מסתירה חבורה של קסם! אנימציות JavaScript דורשות קצת יותר הגדרה וניקוי כדי לעבוד בצורה נכונה רק בגודל מסך אחד ספציפי. ראיתי זוועות בעבר שבהם אנשים פשוט הסתירו את האנימציה מהתצוגה ב-CSS עם opacity: 0, אבל האנימציה עדיין מתרחקת ברקע תוך שימוש במשאבים. 😱

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

gsap.matchMedia() במקום זאת מאפשר לך להכניס בקלות את קוד האנימציה שלך לפונקציה שפועלת רק כאשר מסוים שאילתא מדיה התאמות. ואז, כאשר זה כבר לא תואם, כל האנימציות של GSAP ו ScrollTriggers בפונקציה זו יחזרו אוטומטית. שאילתת המדיה שהאנימציות מוכנסות אליה עושה את כל העבודה הקשה בשבילך. זה ב-GSAP 3.11.0 וזה מחליף משחק!

אנחנו גם לא מוגבלים רק לגדלי מסך. ישנם המון תכונות מדיה שם בחוץ להתחבר!

(prefers-reduced-motion) /* find out if the user would prefer less animation */

(orientation: portrait) /* check the user's device orientation */

(max-resolution: 300dpi) /* check the pixel density of the device */

בהדגמה הבאה הוספנו צ'ק עבור prefers-reduced-motion כך שכל המשתמשים שמוצאים את האנימציה מבלבלת לא יהיו מוטרדים מהדברים שמסתובבים.

ובדוק את ההדגמה המהנה האחרת של טום מילר שבה הוא משתמש ביחס הגובה-רוחב של המכשיר כדי להתאים את האנימציה:

חשיבה מחוץ לקופסה, מעבר לגדלי מסך

יש יותר לחשוב על אנימציה רספונסיבית מאשר רק גדלי מסך. מכשירים שונים מאפשרים אינטראקציות שונות, וקל להסתבך קצת כשלא מתחשבים בזה. אם אתה יוצר מצבי ריחוף ב-CSS, אתה יכול להשתמש ב- hover תכונת מדיה כדי לבדוק אם של המשתמש יְסוֹדִי מנגנון קלט יכול לרחף מעל אלמנטים.

@media (hover: hover) {
 /* CSS hover state here */
}

כמה עצות מ ג'ייק וויטלי:

הרבה מהזמן אנחנו מבססים את ההנפשות שלנו על רוחב הדפדפן, מה שהופך את ההנחה הנאיבית שמשתמשי שולחן העבודה רוצים מצבי ריחוף. היו לי באופן אישי הרבה בעיות בעבר שבהן הייתי עובר לפריסת שולחן עבודה >1024px, אבל אולי יעשה זיהוי מגע ב-JS - מה שמוביל לחוסר התאמה שבו הפריסה הייתה למחשבים שולחניים, אבל ה-JS הייתה למוביילים. בימים אלה אני נשען על הרחף והמצביע כדי להבטיח זוגיות ולטפל ב-ipad Pros או משטחי חלונות (שיכולים לשנות את סוג המצביע תלוי אם הכיסוי מופל או לא)

/* any touch device: */
(hover: none) and (pointer: coarse)
/* iPad Pro */
(hover: none) and (pointer: coarse) and (min-width: 1024px)

לאחר מכן אאחד את שאילתות פריסת ה-CSS שלי ואת שאילתות ה-JavaScript שלי אז אני שוקל את התקן הקלט כגורם העיקרי נתמך לפי רוחב, ולא להיפך.

טיפים של ScrollTrigger

אם אתה משתמש ב-GSAP תוסף ScrollTrigger, יש כלי עזר קטן ושימושי שאתה יכול להתחבר אליו כדי להבחין בקלות ביכולות המגע של המכשיר: ScrollTrigger.isTouch.

  • 0 - אין מגע (מצביע/עכבר בלבד)
  • 1 - מגע בלבד מכשיר (כמו טלפון)
  • 2 - המכשיר יכול לקבל לגעת קלט ו עכבר/מצביע (כמו טאבלטים של Windows)
if (ScrollTrigger.isTouch) {
  // any touch-capable device...
}

// or get more specific: 
if (ScrollTrigger.isTouch === 1) {
  // touch-only device
}

טיפ נוסף לאנימציה מוגברת עם גלילה...

ההדגמה הבאה להלן מעבירה גלריית תמונות אופקית, אך הרוחב משתנה בהתאם לגודל המסך. אם תשנה את גודל המסך כשאתה באמצע אנימציה משופשפת, אתה יכול להסתיים עם אנימציות שבורות וערכים מיושנים. זוהי מחסום מהירות נפוצה, אבל כזו שנפתרת בקלות! הכנס את החישוב התלוי בגודל המסך לערך פונקציונלי והגדר invalidateOnRefresh:true. בדרך זו, ScrollTrigger יחשב מחדש את הערך עבורך כאשר הדפדפן ישתנה.

טיפ חנון GSAP בונוס!

במכשירים ניידים, סרגל הכתובות של הדפדפן בדרך כלל מופיע ומסתתר בזמן הגלילה. זה נחשב כאירוע של שינוי גודל ויגרום להפעלת א ScrollTrigger.refresh(). זה אולי לא אידיאלי מכיוון שהוא יכול לגרום לקפיצות באנימציה שלך. GSAP 3.10 נוסף ignoreMobileResize. זה לא משפיע על איך סרגל הדפדפן מתנהג, אבל זה מונע ScrollTrigger.refresh() מירי עבור שינויי גודל אנכיים קטנים במכשירים למגע בלבד.

ScrollTrigger.config({
  ignoreMobileResize: true
});

עקרונות תנועה

חשבתי להשאיר לך כמה שיטות עבודה מומלצות שכדאי לקחת בחשבון בעת ​​עבודה עם תנועה באינטרנט.

מרחק והקלה

דבר קטן אך חשוב שקל לשכוח עם אנימציה רספונסיבית הוא הקשר בין מהירות, מומנטום ומרחק! אנימציה טובה צריך לחקות את העולם האמיתי להרגיש אמין, ולוקח יותר זמן בעולם האמיתי כדי לעבור מרחק גדול יותר. שימו לב למרחק שהאנימציה שלכם עוברת, וודאו שהמשך וההקלות בהם נעשה שימוש הגיוניים בהקשר עם אנימציות אחרות.

אתה יכול גם לעתים קרובות להחיל הקלות דרמטיות יותר על אלמנטים עם נסיעה נוספת כדי להראות את המומנטום המוגבר:

במקרים מסוימים של שימוש עשוי להיות מועיל להתאים את משך הזמן בצורה דינמית יותר על סמך רוחב המסך. בהדגמה הבאה הזו אנחנו עושים שימוש gsap.utils כדי להדק את הערך שנקבל בחזרה מהזרם window.innerWidth לטווח סביר, אז אנו ממפים את המספר הזה למשך זמן.

מרווח וכמות

דבר נוסף שכדאי לזכור הוא המרווח והכמות של אלמנטים בגדלי מסך שונים. מצטט סטיבן שו:

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

אני אוהב איך אופר וישניה חושב על אנימציה כעל במה. הוספה והסרה של אלמנטים לא חייבת להיות רק עניין פורמלי, זה יכול להיות חלק מהכוריאוגרפיה הכוללת.

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

וזה המגרש. אם יש לך עוד טיפים לאנימציה רספונסיביים, הכנס אותם בקטע התגובות. אם יש משהו מועיל במיוחד, אוסיף אותם לאוסף המידע הזה!

תוֹסֶפֶת

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

כנראה שאיחרתי מדי עם הטיפ הזה למאמר האנימציות הרספונסיביות שלך, אבל אני ממליץ בחום "לסיים את כל האנימציות לפני הבנייה". כרגע אני מתקן כמה אנימציות באתר עם "גרסאות ניידות". תודה לאל על gsap.matchMedia... אבל הלוואי והיינו יודעים שיהיו פריסות/אנימציות לנייד נפרדות מההתחלה.

אני חושב שכולנו מעריכים שהטיפ הזה "לתכנן קדימה" הגיע ברגע האחרון המוחלט. תודה, טום, ובהצלחה עם החידושים האלה.

בול זמן:

עוד מ טריקים של CSS