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 về Tiêu điểm có điều kiện, một cơ chế để các ứng dụng web kiểm soát việc liệu 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ữ nguyên 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 thẻ hoặc cửa sổ, trình duyệt sẽ phải đối mặt với một quyết định — nên đưa giao diện được chụp lên đầu hay trang chụp có nên duy trì làm tâm điểm không? 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 thẻ hoặc cửa sổ đã ghi có thể được điều khiển từ xa, hãy lấy hội nghị truyền hình ở tiêu điểm.
- 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ữ lại tiêu điểm nếu chia sẻ một bản 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ẻ một trình chỉnh sửa 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ổ đã ghi.
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 tiêu điểm 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ể tuỳ ý gọi setFocusBehavior()
nhiều lần trước khi lời hứa được thực hiện hoặc tối đa là 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 getDisplayMedia()
được trả về sẽ phân giải trong 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.
Hãy cho chúng tôi biết 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 hay thuộc tính nào bị thiếu để triển khai ý tưởng của bạn 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 hiện 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 đó.
Gửi một bài đăng đến @ChromiumDev và cho chúng tôi biết bạn đang sử dụng công cụ này ở đâu và bằng cách 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 đã đánh giá bài viết này.