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

François Beaufort
François Beaufort

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

  • Chrome: 109.
  • קצה: 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. חשוב לכלול כמה שיותר פרטים והוראות פשוטות לשחזור הבעיה. תקלה מתאימה לשיתוף קוד.

הצגת תמיכה

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

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

אישורים

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

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