אתם יכולים למחוק את פונקציות הזמן הקצוב לתפוגה ולהיפטר מהבאגים שלהן, כי זה האירוע שאתם באמת צריכים: scrollend.
לפני האירוע scrollend, לא הייתה דרך אמינה לזהות שהגלילה הושלמה. זה אומר שהאירועים הופעלו באיחור או כשהאצבע של המשתמש עדיין הייתה על המסך. חוסר הוודאות לגבי סיום הגלילה בפועל גרם לבאגים ולחוויית משתמש לא טובה.
document.onscroll = event => { clearTimeout(window.scrollEndTimer) window.scrollEndTimer = setTimeout(callback, 100) }
האסטרטגיה הזו של setTimeout() יכולה רק לזהות אם הגלילה הופסקה למשך 100ms. לכן, האירוע הזה דומה יותר לאירוע של השהיית הגלילה, ולא לאירוע של סיום הגלילה.
אחרי האירוע
scrollend
, הדפדפן מבצע את כל ההערכה המורכבת הזו בשבילכם.
document.onscrollend = event => {…}
זה החלק הטוב. התזמון המושלם והתנאים המשמעותיים לפני הפליטה.
כדאי לנסות!
פרטי האירוע
האירוע scrollend מופעל כש:
- הדפדפן כבר לא מציג אנימציה או מתרגם את הגלילה.
- המשתמש הפסיק לגעת במסך.
- המשתמש שחרר את סמן הגלילה.
- המשתמש שחרר את המקש.
- הגלילה לקטע הושלמה.
- הגלילה עם נקודות העצירה (scroll snapping) הסתיימה.
- scrollTo() הסתיימה.
- המשתמש גלל את אזור התצוגה החזותי.
האירוע scrollend לא מופעל במקרים הבאים:
- תנועה של משתמש לא גרמה לשינויים במיקום הגלילה (לא בוצעה תנועה).
- scrollTo() לא תורגם.
אחת מהסיבות לכך שלקח כל כך הרבה זמן להוסיף את האירוע הזה לפלטפורמת האינטרנט היא שהיו הרבה פרטים קטנים שהיה צריך להגדיר. אחד התחומים המורכבים ביותר היה ניסוח הפרטים של scrollend עבור Visual Viewport לעומת המסמך. לדוגמה, דף אינטרנט שאתם מגדילים. אפשר לגלול במצב הזה, אבל לא בהכרח גוללים את המסמך. אל דאגה, גם האינטראקציה הזו של גלילה באזור התצוגה החזותי על ידי המשתמש תפעיל את האירוע scrollend בסיום.
שימוש באירוע
כמו באירועי גלילה אחרים, אפשר לרשום מאזינים בכמה דרכים.
addEventListener("scrollend",> (event) = {
// scroll ended
});
aScrollingElement.addEventListener("scroll>end", (event) = {
// scroll ended
});
או להשתמש במאפיין האירוע:
document.onscrollend = (event) => {
// scroll ended
};
aScrollingElement.onscrollend = (event) => {
// scroll ended
};
Polyfills ושיפור הדרגתי (progressive enhancement)
אם אתם רוצים להשתמש באירוע החדש הזה עכשיו, הנה העצה הכי טובה שלנו. אתם יכולים להמשיך להשתמש בשיטה הקיימת שלכם לסיום הגלילה (אם יש לכם כזו) ובתחילת השיטה לבדוק את התמיכה באמצעות:
'onscrollend' in window
// true, if available
הפונקציה הזו תחזיר את הערך true או false, בהתאם לאירוע שהדפדפן מציע. בעזרת הבדיקה הזו, אפשר להסתעף מהקוד:
if ('onscrollend' in window) {
document.onscrollend = callback
}
else {
document.onscroll => event = {
clearTimeout(window.scrollEndTimer)
window.scrollEndTimer = setTimeout(callback, 100)
}
}
זו התחלה טובה לשיפור הדרגתי של אירוע scrollend כשהוא זמין. אתם יכולים גם לנסות polyfill (NPM) שיצרתי, שמבצע את הפעולה הכי טובה שהדפדפן יכול:
import {scrollend} from "scrollyfills"
// then use scrollend as if it's existed this whole time
document.onscrollend = callback
ה-polyfill ישתפר בהדרגה כדי להשתמש באירוע scrollend המובנה בדפדפן, אם הוא זמין. אם הוא לא זמין, הסקריפט עוקב אחרי אירועי הסמן והגלילה כדי להעריך בצורה הכי טובה שאפשר את סיום האירוע.
תרחישים לדוגמה
מומלץ להימנע מפעולות שדורשות משאבי מחשוב רבים בזמן הגלילה. כך אפשר להשתמש בכמה שיותר זיכרון ועיבוד כדי שהגלילה תהיה חלקה. אירוע scrollend הוא הזמן המושלם להפעיל את הפונקציה ולבצע את העבודה הקשה, כי הגלילה כבר לא מתרחשת.
אפשר להשתמש באירוע scrollend כדי להפעיל פעולות שונות. תרחיש שימוש נפוץ הוא סנכרון של רכיבי ממשק משתמש משויכים עם המיקום שבו הגלילה נעצרה. לדוגמה:
- סנכרון מיקום הגלילה בקרוסלה עם אינדיקטור נקודה.
- סנכרון פריט בגלריה עם המטא-נתונים שלו.
- אחזור נתונים אחרי שמשתמש גולל לכרטיסייה חדשה.
דמיינו תרחיש שבו משתמש מחליק אימייל כדי להסיר אותו. אחרי שהמשתמשים מסיימים להחליק, אפשר לבצע את הפעולה בהתאם למיקום שאליו הם גללו.
אפשר גם להשתמש באירוע הזה לסנכרון אחרי גלילה פרוגרמטית או גלילה של המשתמש, או לפעולות כמו רישום ניתוח נתונים.
זו דוגמה טובה למצב שבו צריך לעדכן כמה רכיבים, כמו חצים, נקודות ומיקוד, בהתאם למיקום הגלילה. ככה יצרתי את הקרוסלה הזו ב-YouTube. אפשר גם לנסות את ההדגמה בשידור חי.
תודה למהדי קזמי (Mehdi Kazemi) על עבודת ההנדסה שלו בנושא הזה, ולרוברט פלאק (Robert Flack) על ההנחיות בנושא API והטמעה.