שיתוף טוב יותר של המסך עם 'התמקדות מותנית'

François Beaufort
François Beaufort

Browser Support

  • Chrome: 109.
  • Edge: 109.
  • Firefox: not supported.
  • Safari: not supported.

Source

Screen Capture API מאפשר למשתמש לבחור כרטיסייה, חלון או מסך לצילום כזרם מדיה. אפשר להקליט את הזרם הזה או לשתף אותו עם אנשים אחרים ברשת. במסמך הזה אנחנו מציגים את התכונה 'מיקוד מותנה', מנגנון שמאפשר לאפליקציות אינטרנט לקבוע אם הכרטיסייה או החלון שצולמו יקבלו מיקוד כשהצילום יתחיל, או אם הדף שממנו מתבצע הצילום יישאר ממוקד.

תמיכה בדפדפנים

התכונה 'פוקוס מותנה' זמינה מגרסה 109 של Chrome.

רקע

כשמתחילים לצלם כרטיסייה או חלון באפליקציית אינטרנט, הדפדפן צריך להחליט אם להעביר את האזור המצולם לחזית או להשאיר את המיקוד בדף שממנו מתבצע הצילום. התשובה תלויה בסיבה להתקשרות getDisplayMedia() ובמשטח שהמשתמש בוחר.

נניח שיש אפליקציית אינטרנט לשיחות ועידה בווידאו. על ידי קריאת track.getSettings().displaySurface ואולי בדיקת Capture Handle, אפליקציית האינטרנט לשיחות ועידה בווידאו יכולה להבין מה המשתמש בחר לשתף. לאחר מכן:

  • אם אפשר לשלוט מרחוק בכרטיסייה או בחלון שמשותפים, כדאי להשאיר את פגישת הווידאו במרכז.
  • אחרת, מעבירים את המיקוד לכרטיסייה או לחלון המוקלטים.

בדוגמה שלמעלה, אפליקציית האינטרנט לשיחות ועידה בווידאו תשמור על המיקוד אם המשתמש ישתף מצגת שקפים, וכך המשתמש יוכל להעביר את השקפים מרחוק. אבל אם המשתמש יבחר לשתף עורך טקסט, המיקוד באפליקציית האינטרנט לשיחות ועידה בווידאו יעבור מיד לכרטיסייה או לחלון שצולמו.

שימוש ב-Conditional Focus API

יוצרים מופע של CaptureController ומעבירים אותו אל getDisplayMedia(). אפשר לקבוע אם הכרטיסייה או החלון שצולמו יקבלו פוקוס או לא, על ידי קריאה ל-setFocusBehavior() מיד אחרי שההבטחה שהוחזרה על ידי getDiplayMedia() נפתרת. אפשר לעשות את זה רק אם המשתמש שיתף כרטיסייה או חלון.

const controller = new CaptureController();  // Prompt the user to share a tab, a window or a screen. const stream =     await navigator.mediaDevices.getDisplayMedia({ controller });  const [track] = stream.getVideoTracks(); const displaySurface = track.getSettings().displaySurface; if (displaySurface == "browser") {   // Focus the captured tab.   controller.setFocusBehavior("focus-captured-surface"); } else if (displaySurface == "window") {   // Do not move focus to the captured window.   // Keep the capturing page focused.   controller.setFocusBehavior("focus-capturing-application"); } 

כשמתלבטים אם להתמקד, אפשר לקחת בחשבון את הלחיצה על ידית ההזזה.

// Retain focus if capturing a tab dialed to example.com. // Focus anything else. const origin = track.getCaptureHandle().origin; if (displaySurface == "browser" && origin == "https://example.com") {   controller.setFocusBehavior("focus-capturing-application"); } else if (displaySurface != "monitor") {   controller.setFocusBehavior("focus-captured-surface"); } 

אפשר אפילו להחליט אם להתמקד לפני שמתקשרים getDisplayMedia().

// Focus the captured tab or window when capture starts. const controller = new CaptureController(); controller.setFocusBehavior("focus-captured-surface");  // Prompt the user to share their screen. const stream =     await navigator.mediaDevices.getDisplayMedia({ controller }); 

אפשר לקרוא ל-setFocusBehavior() מספר פעמים באופן שרירותי לפני שההבטחה נפתרת, או פעם אחת לכל היותר מיד אחרי שההבטחה נפתרת. ההפעלה האחרונה מבטלת את כל ההפעלות הקודמות.

באופן מדויק יותר: - ה-Promise‏ getDisplayMedia() שמוחזר מסתיים במיקרו-משימה. התקשרות אל setFocusBehavior() אחרי השלמת המשימה הקטנה הזו תגרום לשגיאה. – אם מתקשרים setFocusBehavior() יותר משנייה אחרי שהצילום מתחיל, לא מתבצעת פעולה.

כלומר, שני קטעי הקוד הבאים ייכשלו:

// Prompt the user to share their screen. const stream =     await navigator.mediaDevices.getDisplayMedia({ controller });  // Too late, because it follows the completion of the task // on which the getDisplayMedia() promise resolved. // This will throw. setTimeout(() => {   controller.setFocusBehavior("focus-captured-surface"); }); 
// Prompt the user to share their screen. const stream =     await navigator.mediaDevices.getDisplayMedia({ controller });  const start = new Date(); while (new Date() - start <= 1000) {   // Idle for ≈1s. }  // Because too much time has elapsed, the browser will have // already decided whether to focus. // This fails silently. controller.setFocusBehavior("focus-captured-surface"); 

קריאה ל-setFocusBehavior() גם מובילה לשגיאה במקרים הבאים:

  • הסרטון שמוחזר מהסטרימינג של getDisplayMedia() לא משודר בשידור חי.
  • אחרי שההבטחה שהוחזרה getDisplayMedia() נפתרת, אם המשתמש שיתף מסך (לא כרטיסייה או חלון).

דוגמה

כדי להתנסות ב'התמקדות מותנית', אפשר להפעיל את ההדגמה.

זיהוי תכונות

כדי לבדוק אם יש תמיכה ב-CaptureController.setFocusBehavior(), משתמשים בפקודה:

if (   "CaptureController" in window &&   "setFocusBehavior" in CaptureController.prototype ) {   // CaptureController.setFocusBehavior() is supported. } 

משוב

הצוות של Chrome וקהילת תקני האינטרנט רוצים לשמוע על החוויות שלכם עם Conditional Focus.

מתארים את העיצוב

האם יש משהו ב'התמקדות מותנית' שלא פועל כמו שציפית? או שחסרות שיטות או מאפיינים שצריך להטמיע כדי לממש את הרעיון? יש לך שאלה או הערה לגבי מודל האבטחה?

  • אפשר להגיש בקשה לבעיה במפרט במאגר GitHub, או להוסיף את המחשבות שלכם לבעיה קיימת.

בעיה בהטמעה?

מצאתם באג בהטמעה של Chrome? או שההטמעה שונה מהמפרט?

  • מדווחים על הבאג בכתובת https://new.crbug.com. חשוב לכלול כמה שיותר פרטים והוראות פשוטות לשחזור הבאג.

תמיכה ביוצרים

האם אתם מתכננים להשתמש בהתמקדות מותנית? התמיכה הציבורית שלכם עוזרת לצוות Chrome לתעדף תכונות ומראה לספקי דפדפנים אחרים עד כמה חשוב לתמוך בהן.

אתם יכולים לשלוח ציוץ אל @ChromiumDev ולספר לנו איפה ואיך אתם משתמשים בו.

תודות

תמונה ראשית (Hero) של Elena Taranenko.

תודה לרייצ'ל אנדרו על בדיקת המאמר הזה.