แชร์หน้าจอได้ดียิ่งขึ้นด้วยโฟกัสแบบมีเงื่อนไข

François Beaufort
François Beaufort

การรองรับเบราว์เซอร์

  • Chrome: 109
  • ขอบ: 109
  • Firefox: ไม่สนับสนุน
  • Safari: ไม่รองรับ

แหล่งที่มา

API การจับภาพหน้าจอช่วยให้ผู้ใช้เลือกแท็บ หน้าต่าง หรือหน้าจอเพื่อจับภาพเป็นสตรีมสื่อได้ จากนั้นจะสามารถบันทึกหรือแชร์สตรีมนี้กับผู้อื่นผ่านเครือข่ายได้ เอกสารประกอบนี้จะแนะนำการโฟกัสแบบมีเงื่อนไข ซึ่งเป็นกลไกสำหรับเว็บแอปในการควบคุมว่าแท็บหรือหน้าต่างที่บันทึกจะโฟกัสเมื่อเริ่มต้นการจับภาพ หรือต้องการโฟกัสหน้าการจับภาพต่อไป

การสนับสนุนเบราว์เซอร์

การโฟกัสแบบมีเงื่อนไขพร้อมให้ใช้งานใน Chrome 109

ข้อมูลเบื้องต้น

เมื่อเว็บแอปเริ่มจับภาพแท็บหรือหน้าต่าง เบราว์เซอร์จะตัดสินว่าต้องจับภาพบริเวณใดเป็นพิเศษ หรือหน้าจับภาพควรโฟกัสไว้ คำตอบขึ้นอยู่กับเหตุผลที่โทรหา getDisplayMedia() และสุดท้ายที่ผู้ใช้เลือกเมื่อไปถึง

ลองใช้เว็บแอปการประชุมทางวิดีโอที่สมมติขึ้น เมื่ออ่าน track.getSettings().displaySurface และอาจตรวจสอบ Capture Handle แล้ว เว็บแอปการประชุมทางวิดีโอจะเข้าใจสิ่งที่ผู้ใช้เลือกแชร์ได้ จากนั้นให้ทำดังนี้

  • หากควบคุมแท็บหรือหน้าต่างที่บันทึกไว้จากระยะไกลได้ ให้โฟกัสที่การประชุมทางวิดีโอ
  • หรือโฟกัสแท็บหรือหน้าต่างที่จับภาพไว้

ในตัวอย่างข้างต้น เว็บแอปการประชุมทางวิดีโอจะคงโฟกัสไว้หากแชร์ชุดสไลด์ ซึ่งจะช่วยให้ผู้ใช้พลิกดูสไลด์จากระยะไกลได้ แต่หากผู้ใช้เลือกแชร์โปรแกรมแก้ไขข้อความ เว็บแอปการประชุมทางวิดีโอจะเปลี่ยนโฟกัสไปยังแท็บหรือหน้าต่างที่บันทึกไว้ทันที

การใช้ Focusal 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() สำเร็จเกี่ยวกับ Microtask การเรียกใช้ setFocusBehavior() หลังจาก microtask เสร็จสมบูรณ์ทำให้เกิดข้อผิดพลาด - การเรียกใช้ 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() ได้รับการแก้ไขแล้ว หากผู้ใช้แชร์หน้าจอ (ไม่ใช่แท็บหรือหน้าต่าง)

ตัวอย่าง

คุณใช้โฟกัสแบบมีเงื่อนไขได้โดยเรียกใช้การสาธิตใน Glitch อย่าลืมดูซอร์สโค้ด

การตรวจหาฟีเจอร์

หากต้องการตรวจสอบว่าระบบรองรับ CaptureController.setFocusBehavior() หรือไม่ ให้ใช้

if (
  "CaptureController" in window &&
  "setFocusBehavior" in CaptureController.prototype
) {
  // CaptureController.setFocusBehavior() is supported.
}

ความคิดเห็น

ทีม Chrome และชุมชนมาตรฐานเว็บต้องการทราบประสบการณ์ของคุณเกี่ยวกับโฟกัสแบบมีเงื่อนไข

บอกให้เราทราบเกี่ยวกับการออกแบบ

มีบางอย่างเกี่ยวกับโฟกัสตามเงื่อนไขที่ไม่ทำงานตามที่คุณคาดหวังไหม หรือขาดวิธีการหรือคุณสมบัติที่จำเป็นซึ่งจำเป็นต่อการนำไอเดียของคุณไปปฏิบัติ หากมีคำถามหรือความคิดเห็นเกี่ยวกับรูปแบบการรักษาความปลอดภัย

  • ยื่นข้อมูลจำเพาะในที่เก็บของ GitHub หรือเพิ่มความเห็นเกี่ยวกับปัญหาที่มีอยู่

หากมีปัญหาในการติดตั้งใช้งาน

คุณพบข้อบกพร่องในการติดตั้งใช้งาน Chrome ไหม หรือการติดตั้งใช้งานแตกต่างจากข้อกําหนดหรือไม่

  • รายงานข้อบกพร่องที่ https://new.crbug.com โปรดใส่รายละเอียดให้มากที่สุดเท่าที่ทำได้ และวิธีการง่ายๆ ในการทำให้เนื้อหาเกิดซ้ำ Glitch ทำงานได้ดีสำหรับการแชร์โค้ด

แสดงการสนับสนุน

คุณวางแผนจะใช้การโฟกัสแบบมีเงื่อนไขไหม การสนับสนุนสาธารณะของคุณช่วยให้ทีม Chrome จัดลำดับความสำคัญของฟีเจอร์และแสดงให้ผู้ให้บริการเบราว์เซอร์รายอื่นๆ ทราบว่าการสนับสนุนนั้นสำคัญเพียงใด

ส่งทวีตไปที่ @ChromiumDev และแจ้งให้เราทราบว่าคุณใช้งานที่ไหนและอย่างไร

กิตติกรรมประกาศ

รูปภาพหลักโดย Elena Taranenko

ขอขอบคุณ Rachel Andrew ที่อ่านบทความนี้