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

ฟร็องซัว โบฟอร์
François Beaufort
เอลัด อลอน
Elad Alon

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

  • 109
  • 109
  • x
  • x

แหล่งที่มา

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

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

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

ที่มา

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

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

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

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

การใช้ Conditional 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() ได้หลายครั้งตามต้องการก่อนที่สัญญาจะสิ้นสุด หรือไม่เกิน 1 ครั้งหลังจากที่สัญญาสิ้นสุดลง การเรียกใช้ล่าสุดจะลบล้างคำขอก่อนหน้าทั้งหมด

แม่นยำยิ่งขึ้น: - คำมั่นสัญญา 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 และอย่าลืมใส่รายละเอียดให้มากที่สุด รวมถึงวิธีการง่ายๆ ในการผลิตซ้ำ ภาพแตกเหมาะสำหรับการแชร์รหัส

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

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

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

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

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

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