Screen Capture API ช่วยให้ผู้ใช้เลือกแท็บ หน้าต่าง หรือหน้าจอที่จะจับภาพเป็นสตรีมสื่อได้ จากนั้นจะบันทึกหรือแชร์สตรีมนี้กับผู้อื่นผ่านเครือข่ายก็ได้ เอกสารนี้จะแนะนำ Conditional Focus ซึ่งเป็นกลไกสำหรับเว็บแอปในการควบคุมว่าจะให้แท็บหรือหน้าต่างที่จับภาพอยู่ในโฟกัสเมื่อการจับภาพเริ่มต้นขึ้น หรือจะให้หน้าเว็บที่จับภาพอยู่ในโฟกัสต่อไป
การสนับสนุนเบราว์เซอร์
Conditional Focus พร้อมใช้งานใน Chrome 109 เป็นต้นไป
ฉากหลัง
เมื่อเว็บแอปเริ่มจับภาพแท็บหรือหน้าต่าง เบราว์เซอร์จะต้องตัดสินใจว่าจะนำพื้นผิวที่จับภาพมาไว้เบื้องหน้า หรือจะให้หน้าเว็บที่จับภาพอยู่ในโฟกัสต่อไป คำตอบขึ้นอยู่กับเหตุผลที่เรียกใช้ getDisplayMedia() และพื้นผิวที่ผู้ใช้เลือก
ลองพิจารณาเว็บแอปการประชุมทางวิดีโอ สมมติ โดยการอ่าน track.getSettings().displaySurface และอาจตรวจสอบ Capture Handle เว็บแอปการประชุมทางวิดีโอจะเข้าใจสิ่งที่ผู้ใช้เลือกที่จะแชร์ จากนั้นให้ทำดังนี้
- หากควบคุมแท็บหรือหน้าต่างที่จับภาพจากระยะไกลได้ ให้การประชุมทางวิดีโออยู่ในโฟกัส
- หากควบคุมไม่ได้ ให้โฟกัสแท็บหรือหน้าต่างที่จับภาพ
ในตัวอย่างข้างต้น เว็บแอปการประชุมทางวิดีโอจะยังคงอยู่ในโฟกัสหากแชร์ชุดสไลด์ ซึ่งจะช่วยให้ผู้ใช้พลิกดูสไลด์จากระยะไกลได้ แต่หากผู้ใช้เลือกที่จะแชร์เครื่องมือแก้ไขข้อความ เว็บแอปการประชุมทางวิดีโอจะเปลี่ยนโฟกัสไปที่แท็บหรือหน้าต่างที่จับภาพทันที
การใช้ Conditional Focus API
สร้างอินสแตนซ์ CaptureController แล้วส่งไปยัง getDisplayMedia() การเรียกใช้ setFocusBehavior() ทันทีหลังจากที่ Promise ที่แสดงผลโดย 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");
}
เมื่อตัดสินใจว่าจะให้โฟกัสหรือไม่ คุณสามารถพิจารณา Capture Handle ได้
// 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() ได้หลายครั้งตามต้องการก่อนที่สัญญาจะได้รับการแก้ไข หรือเรียกใช้ได้มากที่สุด 1 ครั้งทันทีหลังจากที่สัญญาได้รับการแก้ไข การเรียกใช้ครั้งล่าสุดจะลบล้างการเรียกใช้ก่อนหน้านี้ทั้งหมด
โดยมีรายละเอียดดังนี้
- สัญญาที่แสดงผลโดย
getDisplayMedia()จะได้รับการแก้ไขในไมโครแทสก์ การเรียกใช้setFocusBehavior()หลังจากไมโครแทสก์นั้นเสร็จสมบูรณ์แล้วจะทำให้เกิดข้อผิดพลาด - การเรียกใช้
setFocusBehavior()หลังจากเริ่มการจับภาพไปแล้วมากกว่า 1 วินาทีจะไม่มีผล
นั่นคือข้อมูลโค้ดทั้ง 2 ต่อไปนี้จะล้มเหลว
// 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()ได้รับการแก้ไขแล้ว หากผู้ใช้แชร์หน้าจอ (ไม่ใช่แท็บหรือหน้าต่าง)
ตัวอย่าง
คุณสามารถลองใช้ Conditional Focus ได้โดยเรียกใช้เดโม
การตรวจหาฟีเจอร์
หากต้องการตรวจสอบว่าระบบรองรับ CaptureController.setFocusBehavior() หรือไม่ ให้ใช้โค้ดต่อไปนี้
if (
"CaptureController" in window &&
"setFocusBehavior" in CaptureController.prototype
) {
// CaptureController.setFocusBehavior() is supported.
}
ความคิดเห็น
ทีม Chrome และชุมชนมาตรฐานเว็บอยากทราบความคิดเห็นของคุณเกี่ยวกับประสบการณ์การใช้งาน Conditional Focus
บอกเราเกี่ยวกับการออกแบบ
มีบางอย่างเกี่ยวกับ Conditional Focus ที่ไม่ทำงานตามที่คุณคาดหวังไว้ไหม หรือมีเมธอดหรือพร็อพเพอร์ตี้ที่ขาดหายไปซึ่งคุณต้องใช้เพื่อนำแนวคิดไปใช้ไหม หากมีคำถามหรือความคิดเห็นเกี่ยวกับโมเดลความปลอดภัย
- โปรดแจ้งปัญหาเกี่ยวกับข้อกำหนดในที่เก็บ GitHub หรือเพิ่มความคิดเห็นของคุณในปัญหาที่มีอยู่
พบปัญหาในการใช้งานใช่ไหม
คุณพบข้อบกพร่องในการใช้งานของ Chrome ใช่ไหม หรือการใช้งานแตกต่างจากข้อกำหนดใช่ไหม
- โปรดแจ้งข้อบกพร่องที่ https://new.crbug.com อย่าลืมระบุรายละเอียดให้มากที่สุดเท่าที่จะทำได้ รวมถึงวิธีการจำลองปัญหาซ้ำ
แสดงการสนับสนุน
คุณวางแผนที่จะใช้ Conditional Focus ใช่ไหม การสนับสนุนจากสาธารณะจะช่วยให้ทีม Chrome จัดลำดับความสำคัญของฟีเจอร์และแสดงให้ผู้ให้บริการเบราว์เซอร์รายอื่นๆ เห็นว่าการรองรับฟีเจอร์นี้มีความสำคัญเพียงใด
ส่งทวีตไปที่ @ChromiumDev และบอกให้เราทราบว่าคุณใช้ฟีเจอร์นี้ที่ไหนและอย่างไร
ลิงก์ที่มีประโยชน์
คำขอบคุณ
ขอขอบคุณ Rachel Andrew ที่รีวิวเอกสารนี้