בעבר היה קל להצביע על דברים באינטרנט. היה לך עכבר, הזזת אותו לפעמים לחצת על לחצנים, וזהו. כל מה שלא היה התבצע אמולציה של העכבר, והמפתחים ידעו בדיוק על מה הם יכולים להסתמך.
פשוט לא בהכרח אומר טוב. עם הזמן היא הלכה וגדלה חשוב שלא הכול היה (או התחזה) עכבר: אפשר היה עטים רגישים ללחץ ומבוססי הטיה, לקבלת חופש יצירתי מדהים; אפשר להשתמש באצבעות, אז כל מה שהיה צריך זה המכשיר והיד שלכם, והי, למה לא להשתמש ביותר מאצבע אחת תוך כדי תנועה?
היו לנו אירועי מגע במשך זמן מה כדי לעזור לנו בעניין הזה, אבל זה ממשק 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
|
המצביע שזוהה שוחרר. |
סוגי קלט שונים
באופן כללי, אירועי מצביע מאפשרים לכתוב קוד באופן שלא תלוי בקלט,
בלי שתצטרכו לרשום handlers נפרדים לאירועים עבור מכשירים שונים לקליטת נתונים.
כמובן שעדיין תצטרכו להיות מודעים להבדלים בין סוגי הקלט, למשל
העיקרון של העברת העכבר חל. אם ברצונך להבדיל בין סוגים שונים של מכשירי קלט – אולי כדי לציין
קוד/פונקציונליות נפרדים למקורות קלט שונים. עם זאת, ניתן לעשות זאת
בתוך אותם גורמים מטפלים באירועים באמצעות המאפיין 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.'));
מהירות מובנית: המודל הזה מאפשר ביצועים טובים יותר כברירת מחדל, בהשוואה לאירועי מגע, שבהם צריך להשתמש רכיבי event listener פסיביים כדי להשיג אותה רמת רספונסיביות.
אפשר למנוע מהדפדפן להשתלט על
touch-action
נכס CSS. הגדרת הערך none
ברכיב כלשהו תשבית את כל האפשרויות
פעולות שמוגדרות על ידי הדפדפן התחילו באלמנט הזה. אבל יש כמה
ערכים אחרים לשליטה פרטנית יותר, כמו pan-x
, כדי לאפשר
לדפדפן כדי להגיב לתנועה על ציר ה-X אבל לא על ציר ה-Y. Chrome 55
אפשר להזין את הערכים הבאים:
auto
|
ברירת מחדל; הדפדפן יכול לבצע כל פעולת ברירת מחדל. |
none
|
לדפדפן אין הרשאה לבצע פעולות ברירת מחדל. |
pan-x
|
הדפדפן מורשה לבצע רק את פעולת ברירת המחדל לגלילה אופקית. |
pan-y
|
הדפדפן מורשה לבצע רק את פעולת ברירת המחדל לגלילה אנכית. |
pan-left
|
הדפדפן יכול לבצע רק את פעולת ברירת המחדל של הגלילה האופקית, ורק כדי להזיז את הדף שמאלה. |
pan-right
|
הדפדפן יכול לבצע רק את פעולת ברירת המחדל של הגלילה האופקית, ורק כדי להזיז את הדף ימינה. |
pan-up
|
הדפדפן מורשה לבצע רק את פעולת ברירת המחדל של גלילה אנכית, ורק כדי להזיז את הדף למעלה. |
pan-down
|
הדפדפן מורשה לבצע רק את פעולת ברירת המחדל של גלילה אנכית, ורק כדי להזיז את הדף למטה. |
manipulation
|
הדפדפן מורשה לבצע פעולות גלילה ושינוי מרחק התצוגה בלבד. |
צילום מצביע
העברת אף פעם שעה מתסכלת לניפוי באגים ב-mouseup
לא תקינים
האירוע, עד שתבין שהסיבה לכך היא שהמשתמש משחרר את הלחצן
מחוץ ליעד הקליקים? לא, נכון? אוקיי, אולי זה רק אני.
ועדיין, עד עכשיו לא הייתה דרך ממש טובה להתמודד עם בעיה זו. בטח,
אפשר להגדיר את ה-handler של 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!'));
תמיכה בדפדפנים
נכון למועד הכתיבה, אירועי מצביע נתמכים ב-Internet Explorer 11, Microsoft Edge, Chrome ו-Opera, וגם תמיכה חלקית ב-Firefox. אפשר תוכלו למצוא רשימה עדכנית בכתובת caniuse.com.
אפשר להשתמש ב-polyfill של אירועי המצביע עבור למלא את הפערים האלה. אפשרות אחרת היא לחפש תמיכה של הדפדפן בזמן הריצה פשוט:
if (window.PointerEvent) {
// Yay, we can use pointer events!
} else {
// Back to mouse and touch events, I guess.
}
אירועי מצביע הם כמועמדים אדירים לשיפור הדרגתי:
שינוי שיטות האתחול כדי לבצע את הבדיקה שלמעלה, הוספת אירוע של מצביע
handlers בבלוק if
, ומעבירים את הגורמים המטפלים באירועים של העכבר או המגע אל
חסימת else
.
אז קדימה, אנחנו מזמינים אותך להתנסות ולספר לנו מה דעתך.