scopeMotion: همهٔ انیمیشنهای Motion با یه دستور جمع میشن
خلاصهٔ کاملتر
کتابخونهٔ Motion تو مستنداتش تابع scopeMotion رو معرفی کرده. این تابع هر چیزی که داخلش شروع کنی رو جمع میکنه: انیمیشنها، gestureها و listenerهای scroll و viewport. بعد با یه دستور میتونی همهشون رو stop یا cancel کنی. طبق مستندات، بدون scope هر کدوم از این تابعها یه cleanup جدا برمیگردونن و باید حساب همهشون رو داشته باشی؛ برای یه انیمیشن مشکلی نیست، ولی برای یه صفحهٔ پر از انیمیشن شلوغ میشه.
const scope = scopeMotion(() => {
animate(".box", { x: 100 })
hover(".button", (element) => animate(element, { scale: 1.1 }))
inView(".card", (element) => animate(element, { opacity: 1 }))
})
scope.cancel()scope کار تابعهایی مثل animate، scroll، inView، hover، press، drag، resize و delay رو جمع میکنه. انیمیشنهایی که توی callbackهای inView، hover یا drag شروع بشن هم جزو scope حساب میشن، ولی callbackهای resize نه. فرق stop() و cancel() اینه که stop() عناصر رو همونجا که هستن ول میکنه، ولی cancel() اتریبیوت style عناصر رو برمیگردونه به حالت اول. scope.state هم سه حالت active، stopped و cancelled داره تا کد async قبل از شروع انیمیشن جدید چکش کنه.
یه نکتهٔ مهم: کاری که بعداً شروع بشه، مثلاً تو setTimeout یا بعد از یه await، بیرون scope اجرا میشه. برای اینکه اونم جمع بشه باید با scope.run() یا scope.bind() بپیچونیش. برای تایمرها هم بهتره به جای setTimeout از delay استفاده کنی تا با توقف scope، تایمر هم لغو بشه. برعکسش هم هست: scope.ignore() کاری رو بیرون scope اجرا میکنه که با توقف scope ادامه پیدا کنه.
بخش جذابتر گزینهٔ matchMedia هست که setup رو فقط وقتی یه media query برقراره اجرا میکنه. وقتی شرط عوض بشه، Motion همهچیز رو مثل cancel() پاک میکنه و اگه شرط جدید match بشه دوباره setup رو اجرا میکنه. یعنی وقتی کاربر پنجره رو از دسکتاپ به موبایل کوچیک میکنه، هیچ inline styleی از انیمیشنهای دسکتاپ نمیمونه. shorthandهایی مثل >=800، reducedMotion، touch و dark هم داره و با ! میشه منفیشون کرد.
گزینههای دیگه هم هست: با دادن یه root element، selectorها فقط داخل همون عنصر پیدا میشن. گزینهٔ transition یه transition پیشفرض برای همهٔ animateها تعیین میکنه. scope.refresh() بعد از اضافه شدن محتوای جدید همهچیز رو از نو میسازه و scopeهای تودرتو هم با لغو scope بیرونی لغو میشن. محدودیتهاش هم گفته شده: effectهایی مثل styleEffect با توقف scope متوقف نمیشن و کار شروعشده تو promise یا تایمر داخل setup جمع نمیشه.
نکات کلیدی:
- scopeMotion از پکیج motion import میشه و setup رو بلافاصله اجرا میکنه.
- stop() استایلها رو نگه میداره ولی cancel() اتریبیوت style رو برمیگردونه.
- کار داخل setTimeout یا بعد از await جمع نمیشه مگه با scope.bind() یا scope.run().
- matchMedia هم media query کامل قبول میکنه هم shorthandهایی مثل >=800 !touch.
- callbackهای resize و effectهایی مثل styleEffect جزو scope نیستن.




