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

François Beaufort
François Beaufort

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

  • Chrome: 109.
  • Edge: 109.
  • Firefox: לא נתמך.
  • Safari: לא נתמך.

מקור

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

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

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

רקע

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

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

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

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

שימוש ב-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() כמה פעמים שרוצים לפני שההבטחה מתקבלת, או לכל היותר פעם אחת מיד אחרי שההבטחה מתקבלת. ההפעלה האחרונה מבטלת את כל ההפעלות הקודמות.

באופן מדויק יותר: - ההבטחה getDisplayMedia() שמוחזרת מתקבלת ב-microtask. קריאה ל-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() שהוחזרה מתקבלת, אם המשתמש שיתף מסך (לא כרטיסייה או חלון).

דוגמה

כדי לשחק עם התכונה 'מיקוד מותנה', אפשר להריץ את הדמו ב-Glitch. חשוב לבדוק את קוד המקור.

זיהוי תכונות

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

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

משוב

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

נשמח לשמוע על העיצוב

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

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

בעיה בהטמעה?

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

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

הצגת תמיכה

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

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

תודות

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

תודה ל-Rachel Andrew על בדיקת המאמר.