رابط برنامهنویسی کاربردی ضبط صفحه نمایش (Screen Capture API) به کاربر اجازه میدهد تا یک تب، پنجره یا صفحه را برای ضبط به عنوان یک جریان رسانهای انتخاب کند. سپس این جریان میتواند ضبط شود یا از طریق شبکه با دیگران به اشتراک گذاشته شود. این مستندات، تمرکز شرطی (Conditional Focus) را معرفی میکند، مکانیزمی برای برنامههای وب که کنترل میکنند آیا تب یا پنجره ضبط شده هنگام شروع ضبط در حالت فوکوس قرار گیرد یا اینکه صفحه ضبط شده در حالت فوکوس باقی بماند.
پشتیبانی مرورگر
فوکوس شرطی از کروم ۱۰۹ در دسترس است.
پیشینه
وقتی یک برنامه وب شروع به ضبط یک تب یا پنجره میکند، مرورگر با یک تصمیم روبرو میشود - آیا سطح ضبط شده باید به جلو آورده شود یا صفحه ضبط شده باید متمرکز باقی بماند؟ پاسخ به دلیل فراخوانی getDisplayMedia() و سطحی که کاربر در نهایت انتخاب میکند بستگی دارد.
یک برنامه وب کنفرانس ویدیویی فرضی را در نظر بگیرید. با خواندن track.getSettings().displaySurface و بررسی احتمالی Capture Handle ، برنامه وب کنفرانس ویدیویی میتواند بفهمد که کاربر چه چیزی را برای اشتراکگذاری انتخاب کرده است. سپس:
- اگر تب یا پنجره ضبط شده قابل کنترل از راه دور است، کنفرانس ویدیویی را در کانون توجه قرار دهید.
- در غیر این صورت، زبانه یا پنجرهی گرفتهشده را فوکوس کنید.
در مثال بالا، برنامه وب کنفرانس ویدیویی در صورت اشتراکگذاری یک دسته اسلاید، فوکوس را حفظ میکند و به کاربر اجازه میدهد از راه دور اسلایدها را ورق بزند؛ اما اگر کاربر تصمیم به اشتراکگذاری یک ویرایشگر متن بگیرد، برنامه وب کنفرانس ویدیویی بلافاصله فوکوس را به برگه یا پنجره ضبط شده تغییر میدهد.
استفاده از 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");
}
هنگام تصمیمگیری در مورد فوکوس کردن، میتوان دستگیرهی ثبت تصویر را در نظر گرفت.
// 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() را به دلخواه بارها قبل از اتمام promise یا حداکثر یک بار بلافاصله پس از اتمام promise فراخوانی کنید. آخرین فراخوانی، تمام فراخوانیهای قبلی را لغو میکند.
دقیقتر:
- تابع
getDisplayMedia() یک ریزوظیفه را حل میکند. فراخوانیsetFocusBehavior() پس از اتمام آن ریزوظیفه، خطا میدهد. - فراخوانی تابع
setFocusBehavior()بیش از یک ثانیه پس از شروع ضبط، عملی نیست.
یعنی، هر دو قطعه کد زیر با شکست مواجه خواهند شد:
// 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()promise را برگرداند، اگر کاربر صفحهای را به اشتراک گذاشته باشد (نه یک تب یا پنجره)، این کار انجام میشود.
نمونه
شما میتوانید با اجرای نسخه آزمایشی، با تمرکز شرطی کار کنید.
تشخیص ویژگی
برای بررسی اینکه آیا CaptureController.setFocusBehavior() پشتیبانی میشود یا خیر، از دستور زیر استفاده کنید:
if (
"CaptureController" in window &&
"setFocusBehavior" in CaptureController.prototype
) {
// CaptureController.setFocusBehavior() is supported.
}
بازخورد
تیم کروم و جامعه استانداردهای وب میخواهند از تجربیات شما در مورد تمرکز شرطی بشنوند.
در مورد طراحی به ما بگویید
آیا موردی در مورد تمرکز شرطی وجود دارد که آنطور که انتظار داشتید کار نمیکند؟ یا متدها یا ویژگیهایی وجود ندارند که برای پیادهسازی ایده خود به آنها نیاز دارید؟ در مورد مدل امنیتی سؤال یا نظری دارید؟
- یک مشکل خاص را در مخزن گیتهاب ثبت کنید، یا نظرات خود را به یک مشکل موجود اضافه کنید.
مشکل در اجرا؟
آیا در پیادهسازی کروم اشکالی پیدا کردید؟ یا پیادهسازی با مشخصات متفاوت است؟
- یک اشکال را در https://new.crbug.com ثبت کنید. حتماً تا حد امکان جزئیات و دستورالعملهای مربوط به تکثیر را ذکر کنید.
نمایش پشتیبانی
آیا قصد دارید از تمرکز شرطی استفاده کنید؟ حمایت عمومی شما به تیم کروم کمک میکند تا ویژگیها را در اولویت قرار دهد و به سایر فروشندگان مرورگر نشان میدهد که پشتیبانی از آنها چقدر حیاتی است.
یک توییت به @ChromiumDev ارسال کنید و به ما بگویید که کجا و چگونه از آن استفاده میکنید.
لینکهای مفید
تقدیرنامهها
با تشکر از ریچل اندرو برای بررسی این سند.