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

פרנסואה בופורט
פרנסואה בופורט
אלעד אלון
אלעד אלון

תמיכה בדפדפן

  • 109
  • 109
  • x
  • x

מקור

ה-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() שהוחזרה טופלה במיקרו-משימה. קריאה ל-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.