اشاره کردن به چیزهایی در وب قبلا ساده بود. شما یک ماوس داشتید، آن را جابهجا میکردید، گاهی اوقات دکمهها را فشار میدادید و تمام. هر چیزی که ماوس نبود به عنوان یک موش شبیه سازی شد و توسعه دهندگان دقیقا می دانستند روی چه چیزی باید حساب کنند.
هرچند ساده لزوماً به معنای خوب نیست. با گذشت زمان، اهمیت فزاینده ای پیدا کرد که همه چیز یک موش (یا تظاهر به آن) نیست: شما می توانید قلم های حساس به فشار و کج را برای آزادی خلاق شگفت انگیز داشته باشید. میتوانستید از انگشتانتان استفاده کنید، بنابراین تنها چیزی که نیاز داشتید دستگاه و دستتان بود. و هی، چرا در حالی که در آن هستید از بیش از یک انگشت استفاده نکنید؟
مدتی است که رویدادهای لمسی برای کمک به ما داشتهایم، اما آنها یک API کاملاً مجزا برای لمس هستند و اگر میخواهید از ماوس و لمس پشتیبانی کنید، مجبورید دو مدل رویداد جداگانه را کدنویسی کنید. Chrome 55 با استاندارد جدیدتری عرضه میشود که هر دو مدل را متحد میکند: رویدادهای اشارهگر.
یک مدل رویداد واحد
رویدادهای اشاره گر مدل ورودی اشاره گر را برای مرورگر یکسان می کند و لمس، قلم ها و موش ها را در یک مجموعه واحد از رویدادها با هم ترکیب می کند. به عنوان مثال:
document.addEventListener('pointermove',
ev => console.log('The pointer moved.'));
foo.addEventListener('pointerover',
ev => console.log('The pointer is now over foo.'));
در اینجا لیستی از تمام رویدادهای موجود وجود دارد که اگر با رویدادهای ماوس آشنایی دارید، باید بسیار آشنا به نظر برسند:
pointerover | اشاره گر وارد کادر محدود کننده عنصر شده است. این بلافاصله برای دستگاههایی که از شناور پشتیبانی میکنند یا قبل از یک رویداد pointerdown برای دستگاههایی که پشتیبانی نمیکنند اتفاق میافتد. |
pointerenter | شبیه pointerover است، اما حباب نمی دهد و فرزندان را به طور متفاوتی اداره می کند. جزئیات در مورد مشخصات |
pointerdown | بسته به معنایی دستگاه ورودی، نشانگر وارد حالت دکمه فعال شده است، با فشار دادن دکمه یا برقراری تماس. |
pointermove | نشانگر موقعیت خود را تغییر داده است. |
pointerup | نشانگر از حالت دکمه فعال خارج شده است. |
pointercancel | چیزی اتفاق افتاده است که به این معنی است که بعید است نشانگر رویداد دیگری را منتشر کند. این بدان معنی است که شما باید هر گونه اقدام در حال انجام را لغو کنید و به حالت ورودی خنثی برگردید. |
pointerout | اشاره گر از کادر محدود عنصر یا صفحه خارج شده است. همچنین پس از یک pointerup ، اگر دستگاه از شناور پشتیبانی نمی کند. |
pointerleave | مشابه pointerout است، اما حباب نمی دهد و فرزندان را به طور متفاوتی اداره می کند. جزئیات در مورد مشخصات |
gotpointercapture | عنصر ضبط نشانگر را دریافت کرده است. |
lostpointercapture | اشاره گر که در حال گرفتن بود آزاد شد. |
انواع مختلف ورودی
به طور کلی، Pointer Events به شما امکان می دهد تا کد را به روش ورودی-آگنوستیک بنویسید، بدون نیاز به ثبت کنترل کننده رویداد جداگانه برای دستگاه های ورودی مختلف. البته، همچنان باید به تفاوتهای بین انواع ورودی توجه داشته باشید، مانند اینکه آیا مفهوم شناور کاربرد دارد یا خیر. اگر میخواهید انواع دستگاههای ورودی مختلف را از هم جدا کنید – شاید برای ارائه کد/عملکرد جداگانه برای ورودیهای مختلف – میتوانید با استفاده از ویژگی pointerType
رابط PointerEvent
این کار را از درون کنترلکنندههای رویداد مشابه انجام دهید. برای مثال، اگر یک کشوی ناوبری جانبی را کدنویسی میکردید، میتوانید منطق زیر را در رویداد pointermove
خود داشته باشید:
switch(ev.pointerType) {
case 'mouse':
// Do nothing.
break;
case 'touch':
// Allow drag gesture.
break;
case 'pen':
// Also allow drag gesture.
break;
default:
// Getting an empty string means the browser doesn't know
// what device type it is. Let's assume mouse and do nothing.
break;
}
اقدامات پیش فرض
در مرورگرهای لمسی، از حرکات خاصی برای اسکرول کردن، بزرگنمایی یا تازه کردن صفحه استفاده می شود. در مورد رویدادهای لمسی، در حالی که این اقدامات پیشفرض انجام میشوند، همچنان رویدادها را دریافت خواهید کرد – برای مثال، touchmove
همچنان در حالی که کاربر در حال پیمایش است، فعال میشود.
با رویدادهای اشاره گر، هر زمان که یک عملکرد پیش فرض مانند اسکرول یا بزرگنمایی فعال شود، یک رویداد pointercancel
دریافت می کنید تا به شما اطلاع دهد که مرورگر کنترل نشانگر را به دست گرفته است. به عنوان مثال:
document.addEventListener('pointercancel',
ev => console.log('Go home, the browser is in charge now.'));
سرعت داخلی : این مدل به طور پیشفرض عملکرد بهتری را در مقایسه با رویدادهای لمسی امکانپذیر میکند، جایی که برای دستیابی به همان سطح پاسخدهی باید از شنوندههای رویداد غیرفعال استفاده کنید.
میتوانید با ویژگی CSS touch-action
کنترل مرورگر را متوقف کنید. با تنظیم آن بر روی none
عنصری، تمام اقدامات تعریف شده توسط مرورگر شروع شده روی آن عنصر غیرفعال می شود. اما تعدادی مقادیر دیگر برای کنترل دقیقتر وجود دارد، مانند pan-x
، که به مرورگر اجازه میدهد به حرکت در محور x واکنش نشان دهد، اما نه به محور y. Chrome 55 از مقادیر زیر پشتیبانی می کند:
auto | پیش فرض مرورگر می تواند هر اقدام پیش فرضی را انجام دهد. |
none | مرورگر مجاز به انجام هیچ گونه اقدام پیش فرض نیست. |
pan-x | مرورگر فقط مجاز است عمل پیشفرض اسکرول افقی را انجام دهد. |
pan-y | مرورگر فقط مجاز است عمل پیشفرض پیمایش عمودی را انجام دهد. |
pan-left | مرورگر فقط مجاز است عمل پیشفرض اسکرول افقی را انجام دهد و فقط صفحه را به سمت چپ حرکت دهد. |
pan-right | مرورگر فقط مجاز است عمل پیشفرض اسکرول افقی را انجام دهد و فقط صفحه را به سمت راست حرکت دهد. |
pan-up | مرورگر فقط مجاز است عمل پیشفرض پیمایش عمودی را انجام دهد و فقط صفحه را به بالا حرکت دهد. |
pan-down | مرورگر فقط مجاز است عمل پیشفرض پیمایش عمودی را انجام دهد و فقط صفحه را به پایین حرکت دهد. |
manipulation | مرورگر فقط مجاز به انجام اقدامات اسکرول و بزرگنمایی است. |
گرفتن اشاره گر
آیا تا به حال یک ساعت خسته کننده را صرف اشکال زدایی یک رویداد شکسته mouseup
کرده اید، تا زمانی که متوجه شوید که به این دلیل است که کاربر دکمه خارج از هدف کلیک شما را رها می کند؟ نه؟ باشه، پس شاید فقط من باشم.
با این حال، تا کنون یک راه واقعا خوب برای مقابله با این مشکل وجود نداشت. مطمئناً، میتوانید کنترلکننده mouseup
را روی سند تنظیم کنید و مقداری وضعیت را در برنامه خود ذخیره کنید تا موارد را پیگیری کنید. اگرچه این تمیزترین راه حل نیست، به خصوص اگر در حال ساختن یک مؤلفه وب هستید و سعی می کنید همه چیز را خوب و ایزوله نگه دارید.
با رویدادهای اشاره گر راه حل بسیار بهتری ارائه می شود: می توانید نشانگر را ضبط کنید، به طوری که مطمئن باشید آن رویداد pointerup
(یا هر یک از دوستان گریزان آن) را دریافت خواهید کرد.
const foo = document.querySelector('#foo');
foo.addEventListener('pointerdown', ev => {
console.log('Button down, capturing!');
// Every pointer has an ID, which you can read from the event.
foo.setPointerCapture(ev.pointerId);
});
foo.addEventListener('pointerup',
ev => console.log('Button up. Every time!'));
پشتیبانی از مرورگر
در زمان نگارش، رویدادهای اشاره گر در اینترنت اکسپلورر 11، مایکروسافت اج، کروم و اپرا پشتیبانی می شوند و تا حدی در فایرفاکس پشتیبانی می شوند. می توانید یک لیست به روز را در caniuse.com پیدا کنید.
می توانید از Pointer Events polyfill برای پر کردن شکاف ها استفاده کنید. از طرف دیگر، بررسی پشتیبانی مرورگر در زمان اجرا ساده است:
if (window.PointerEvent) {
// Yay, we can use pointer events!
} else {
// Back to mouse and touch events, I guess.
}
رویدادهای اشاره گر کاندیدای فوق العاده ای برای بهبود تدریجی هستند: فقط روش های اولیه سازی خود را برای بررسی بالا تغییر دهید، کنترل کننده های رویداد اشاره گر را در بلوک if
اضافه کنید و کنترل کننده های رویداد ماوس/لمسی خود را به بلوک else
منتقل کنید.
پس ادامه دهید، به آنها نگاهی بیندازید و نظر خود را به ما بگویید!