Screen Capture API 讓使用者選取要擷取的分頁、視窗或螢幕畫面,做為媒體串流。然後錄製這部直播影片,或是透過網路與他人分享。本文件將介紹「條件聚焦」,這是網頁應用程式的機制,可控制擷取的分頁或視窗是否會在擷取時聚焦,或者擷取網頁是否保持聚焦。
瀏覽器支援
Chrome 109 以上版本才有條件聚焦功能。
背景
網頁應用程式開始擷取某個分頁或視窗時,瀏覽器會做出決定:應該將擷取的介面移至最前方,還是要保持擷取頁面聚焦狀態?答案取決於呼叫 getDisplayMedia()
的原因,以及在使用者選擇的介面上。
假設你使用假想的視訊會議網頁應用程式,閱讀 track.getSettings().displaySurface
內容 (可能會查看擷取帳號代碼) 後,視訊會議網頁應用程式就能瞭解使用者選擇分享的內容。然後執行下列步驟:
- 如果擷取的分頁或視窗可以從遠端控制,請將視訊會議畫面保持在焦點位置。
- 否則焦點會移至已擷取的分頁或視窗。
在上例中,當使用者分享簡報內容時,視訊會議網頁應用程式會保持焦點,讓使用者從遠端翻閱投影片。但如果使用者選擇共用文字編輯器,視訊會議網頁應用程式就會立即將焦點移至擷取的分頁或視窗。
使用條件聚焦 API
將 CaptureController
例項化,並傳遞至 getDisplayMedia()
。在傳回的 getDiplayMedia()
承諾解析後立即呼叫 setFocusBehavior()
,即可控制擷取的分頁或視窗是否會聚焦。使用者必須分享分頁或視窗才能執行這項操作。
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 回報錯誤。請盡可能提供所有細節,並提供重現重現說明的簡單操作說明。Glitch 很適合用來分享代碼。
顯示支援
您是否打算使用「條件式聚焦」?您的公開支援服務可協助 Chrome 團隊優先開發特定功能,並說明其他瀏覽器廠商對於這些功能的支援有多重要。
請將 Twitter 訊息傳送給 @ChromiumDev,並告訴我們您使用何處及使用方式。
實用連結
特別銘謝
主頁橫幅由 Elena Taranenko 提供。
感謝 Rachel Andrew 撰寫這篇文章。