Screen Capture API (API chụp màn hình) cho phép người dùng chọn một thẻ, cửa sổ hoặc màn hình để chụp dưới dạng luồng nội dung nghe nhìn. Sau đó, bạn có thể ghi lại hoặc chia sẻ luồng này với những người khác qua mạng. Tài liệu này giới thiệu Conditional Focus (Tâm điểm có điều kiện), một cơ chế để các ứng dụng web kiểm soát việc thẻ hoặc cửa sổ đã chụp có được lấy tiêu điểm khi bắt đầu chụp hay không, hoặc liệu trang chụp có giữ tiêu điểm hay không.
Hỗ trợ trình duyệt
Tính năng Tiêu điểm có điều kiện có trong Chrome 109.
Thông tin khái quát
Khi một ứng dụng web bắt đầu chụp một thẻ hoặc cửa sổ, trình duyệt sẽ phải đưa ra quyết định – liệu giao diện được chụp có được đưa lên nền trước hay không, hay trang chụp vẫn được lấy làm tiêu điểm? Câu trả lời phụ thuộc vào lý do gọi getDisplayMedia()
và trên nền tảng mà người dùng cuối cùng chọn.
Hãy xem xét một ứng dụng web hội nghị truyền hình giả định. Bằng cách đọc track.getSettings().displaySurface
và có thể kiểm tra Tên người dùng chụp, ứng dụng web hội nghị truyền hình có thể hiểu được nội dung mà người dùng chọn chia sẻ. Sau đó:
- Nếu bạn có thể điều khiển từ xa thẻ hoặc cửa sổ đã chụp, hãy đặt tiêu điểm vào cuộc họp video.
- Nếu không, hãy đặt tiêu điểm vào thẻ hoặc cửa sổ đã ghi lại.
Trong ví dụ trên, ứng dụng web hội nghị truyền hình sẽ giữ tiêu điểm nếu chia sẻ một nhóm trang trình bày, cho phép người dùng lật qua các trang trình bày từ xa; nhưng nếu người dùng chọn chia sẻ trình soạn thảo văn bản, thì ứng dụng web hội nghị truyền hình sẽ ngay lập tức chuyển tiêu điểm sang thẻ hoặc cửa sổ đã chụp.
Sử dụng Conditional Focus API
Tạo thực thể CaptureController
rồi truyền thực thể đó vào getDisplayMedia()
. Bằng cách gọi setFocusBehavior()
ngay sau khi lời hứa trả về getDiplayMedia()
được phân giải, bạn có thể kiểm soát xem thẻ hoặc cửa sổ đã chụp có được lấy tiêu điểm hay không. Bạn chỉ có thể thực hiện việc này nếu người dùng đã chia sẻ một thẻ hoặc cửa sổ.
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");
}
Khi quyết định có lấy nét hay không, bạn có thể cân nhắc Tên tay cầm chụp.
// 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");
}
Bạn thậm chí có thể quyết định có lấy nét hay không trước khi gọi 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 });
Bạn có thể gọi setFocusBehavior()
nhiều lần tuỳ ý trước khi lời hứa được thực hiện hoặc nhiều nhất một lần ngay sau khi lời hứa được thực hiện. Lệnh gọi cuối cùng sẽ ghi đè tất cả lệnh gọi trước đó.
Chính xác hơn:
– Lời hứa trả về getDisplayMedia()
sẽ phân giải trên một tác vụ vi mô. Việc gọi setFocusBehavior()
sau khi tác vụ vi mô đó hoàn tất sẽ gây ra lỗi.
– Việc gọi setFocusBehavior()
sau hơn một giây kể từ khi quá trình chụp bắt đầu sẽ không hoạt động.
Tức là cả hai đoạn mã sau đây đều không thành công:
// 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");
Việc gọi setFocusBehavior()
cũng sẽ gửi trong các trường hợp sau:
- kênh video của luồng do
getDisplayMedia()
trả về không phải là "trực tiếp". - sau khi lời hứa trả về
getDisplayMedia()
được giải quyết, nếu người dùng đã chia sẻ màn hình (không phải thẻ hoặc cửa sổ).
Mẫu
Bạn có thể thử nghiệm với tính năng Tiêu điểm có điều kiện bằng cách chạy bản minh hoạ trên Glitch. Hãy nhớ xem mã nguồn.
Phát hiện tính năng
Để kiểm tra xem CaptureController.setFocusBehavior()
có được hỗ trợ hay không, hãy sử dụng:
if (
"CaptureController" in window &&
"setFocusBehavior" in CaptureController.prototype
) {
// CaptureController.setFocusBehavior() is supported.
}
Phản hồi
Nhóm Chrome và cộng đồng tiêu chuẩn web muốn biết trải nghiệm của bạn với tính năng Tiêu điểm có điều kiện.
Giới thiệu về thiết kế
Có điều gì về Tiêu điểm có điều kiện không hoạt động như mong đợi không? Hay có phương thức hoặc thuộc tính nào bị thiếu mà bạn cần để triển khai ý tưởng của mình không? Bạn có câu hỏi hoặc nhận xét về mô hình bảo mật?
- Gửi vấn đề về thông số kỹ thuật trên kho lưu trữ GitHub hoặc thêm ý kiến của bạn vào một vấn đề hiện có.
Bạn gặp vấn đề khi triển khai?
Bạn có phát hiện lỗi khi triển khai Chrome không? Hay cách triển khai có khác với thông số kỹ thuật không?
- Gửi lỗi tại https://new.crbug.com. Hãy nhớ cung cấp càng nhiều thông tin chi tiết càng tốt và hướng dẫn đơn giản để tái tạo lỗi. Glitch hoạt động hiệu quả để chia sẻ mã.
Thể hiện sự ủng hộ
Bạn có dự định sử dụng tính năng Tiêu điểm có điều kiện không? Sự ủng hộ công khai của bạn giúp nhóm Chrome ưu tiên các tính năng và cho các nhà cung cấp trình duyệt khác thấy tầm quan trọng của việc hỗ trợ các tính năng đó.
Hãy gửi một tweet đến @ChromiumDev và cho chúng tôi biết bạn đang sử dụng công cụ này ở đâu và như thế nào.
Đường liên kết hữu ích
Lời cảm ơn
Hình ảnh chính của Elena Taranenko.
Cảm ơn Rachel Andrew đã xem xét bài viết này.