توابع timeout خود را حذف کنید و اشکالات آنها را برطرف کنید، این رویدادی است که واقعاً به آن نیاز دارید: scrollend.
قبل از رویداد scrollend ، هیچ راه قابل اعتمادی برای تشخیص کامل شدن اسکرول وجود نداشت. این به این معنی بود که رویدادها با تأخیر یا در حالی که انگشت کاربر هنوز روی صفحه بود، اجرا میشدند. این عدم اطمینان در دانستن زمان پایان اسکرول، منجر به اشکالات و تجربه ضعیف برای کاربر میشد.
document.onscroll = event => { clearTimeout(window.scrollEndTimer) window.scrollEndTimer = setTimeout(callback, 100) }
بهترین کاری که این استراتژی setTimeout() میتواند انجام دهد این است که بداند آیا اسکرول به مدت 100ms متوقف شده است یا خیر. این باعث میشود که بیشتر شبیه یک رویداد متوقف شده اسکرول باشد، نه یک رویداد پایان یافته اسکرول.
بعد از رویداد scrollend ، مرورگر تمام این ارزیابی دشوار را برای شما انجام میدهد.
document.onscrollend = event => {…}
این نکتهی خوبیه. کاملاً زمانبندی شده و پر از شرایط معنیدار قبل از انتشار.
امتحانش کن!
جزئیات رویداد
رویداد scrollend زمانی اجرا میشود که: - مرورگر دیگر در حال انیمیشن دادن یا ترجمه اسکرول نباشد. - لمس کاربر رها شده باشد. - اشارهگر کاربر، نشانگر اسکرول را رها کرده باشد. - فشردن کلید کاربر رها شده باشد. - اسکرول به فرگمنت کامل شده باشد. - اسکرول اسنپ کامل شده باشد. - scrollTo() کامل شده باشد. - کاربر نمای بصری را اسکرول کرده باشد.
رویداد scrollend زمانی اجرا نمیشود که: - اشاره کاربر منجر به هیچ تغییر موقعیتی اسکرول نشود (هیچ ترجمهای رخ ندهد). - scrollTo() منجر به هیچ ترجمهای نشود.
یکی از دلایلی که این رویداد اینقدر طول کشید تا به پلتفرم وب برسد، جزئیات کوچک زیادی بود که نیاز به جزئیات مشخصات داشتند. یکی از پیچیدهترین بخشها، بیان جزئیات scrollend برای Visual Viewport در مقابل سند بود. یک صفحه وب را در نظر بگیرید که روی آن زوم میکنید. میتوانید در این حالت زوم، اسکرول کنید و لزوماً سند را اسکرول نمیکنید. مطمئن باشید که حتی این تعامل اسکرول که توسط کاربر در Visual Viewport هدایت میشود، پس از اتمام، رویداد scrollend منتشر خواهد کرد.
با استفاده از رویداد
مانند سایر رویدادهای اسکرول، میتوانید شنوندهها را به چند روش ثبت کنید.
addEventListener("scrollend", (event) => {
// scroll ended
});
aScrollingElement.addEventListener("scrollend", (event) => {
// scroll ended
});
یا از ویژگی رویداد استفاده کنید:
document.onscrollend = (event) => {
// scroll ended
};
aScrollingElement.onscrollend = (event) => {
// scroll ended
};
پلیفیلها و بهبود تدریجی
اگر میخواهید همین الان از این رویداد جدید استفاده کنید، بهترین توصیه ما این است. میتوانید به استفاده از استراتژی فعلی پایان اسکرول خود (در صورت وجود) ادامه دهید و در ابتدای کار، پشتیبانی را با موارد زیر بررسی کنید:
'onscrollend' in window
// true, if available
بسته به اینکه مرورگر این رویداد را ارائه میدهد یا خیر، مقدار درست یا غلط را گزارش میدهد. با این بررسی، میتوانید کد را به شاخههای زیر تقسیم کنید:
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 میتواند برای فعال کردن اقدامات مختلفی استفاده شود. یک مورد استفاده رایج، همگامسازی عناصر رابط کاربری مرتبط با موقعیتی است که پیمایش متوقف شده است. به عنوان مثال: - همگامسازی موقعیت پیمایش یک چرخ فلک با یک نشانگر نقطه. - همگامسازی یک آیتم گالری با دادههای متای آن. - دریافت دادهها پس از پیمایش کاربر به یک برگه جدید.
سناریویی مانند حذف ایمیل توسط کاربر را تصور کنید. پس از اتمام کشیدن انگشت، میتوانید بر اساس جایی که به آن پیمایش کرده است، عمل مورد نظر را انجام دهید.
همچنین میتوانید از این رویداد برای همگامسازی پس از اسکرول کاربر یا برنامهریزیشده یا اقداماتی مانند ثبت تحلیلها استفاده کنید.
در اینجا یک مثال خوب وجود دارد که در آن عناصر متعددی مانند فلشها، نقاط و فوکوس باید بر اساس موقعیت اسکرول بهروزرسانی شوند. نحوه ساخت این چرخ و فلک را در یوتیوب تماشا کنید . همچنین، نسخه آزمایشی زنده را امتحان کنید .
با تشکر از مهدی کاظمی برای کار مهندسیشان روی این پروژه و رابرت فلک برای API و راهنماییهای پیادهسازی.