Interfejs Screen Capture API umożliwia wybór karty, okna lub ekranu, które mają zostać przechwycone jako strumień multimediów. Tę transmisję można potem nagrać lub udostępnić innym osobom w sieci. W tej dokumentacji omawiamy fokus warunkowy – mechanizm używany przez aplikacje internetowe do kontrolowania, czy przechwycona karta lub okno mają być zaznaczone w momencie rozpoczęcia przechwytywania, czy też strona przechwytywania pozostanie aktywna.
Obsługa przeglądarek
Ostrość warunkowa jest dostępna w Chrome 109.
Tło
Gdy aplikacja internetowa rozpoczyna przechwytywanie karty lub okna, przeglądarka musi podjąć decyzję. Czy przechwycona powierzchnia powinna znajdować się na pierwszym planie, czy powinna pozostać aktywna? Odpowiedź zależy od powodu wywołania funkcji getDisplayMedia()
oraz od tego, co użytkownik wybierze.
Rozważ użycie hipotetycznej aplikacji internetowej do prowadzenia rozmów wideo. Jeśli czytasz komunikat track.getSettings().displaySurface
i sprawdzasz nick do przechwytywania, aplikacja internetowa do obsługi rozmów wideo wie, co użytkownik zdecydował się udostępnić. Następnie:
- Jeśli zapisaną kartą lub oknem można sterować zdalnie, upewnij się, że rozmowa wideo jest widoczna.
- W przeciwnym razie zaznacz przechwyconą kartę lub okno.
W powyższym przykładzie aplikacja internetowa do obsługi rozmów wideo zachowałaby fokus, jeśli została udostępniona, ponieważ umożliwia użytkownikowi zdalne przechodzenie między slajdami. Jeśli jednak użytkownik udostępnia edytor tekstu, aplikacja internetowa do obsługi rozmów wideo natychmiast przełącza fokus na przechwyconą kartę lub okno.
Korzystanie z interfejsu Conditional Focus API
Utwórz instancję CaptureController
i przekaż ją do getDisplayMedia()
. Wywołując funkcję setFocusBehavior()
natychmiast po rozwiązaniu zwróconej obietnicy getDiplayMedia()
, możesz określić, czy przechwycona karta lub okno mają być zaznaczone. Można to zrobić tylko wtedy, gdy użytkownik udostępnił kartę lub okno.
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");
}
Podejmując decyzję o tym, czy się skupić, możesz wziąć pod uwagę nick przechwytywania.
// 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");
}
Przed nawiązaniem połączenia z firmą getDisplayMedia()
możesz nawet zdecydować, czy chcesz się skupić.
// 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 });
Możesz wywoływać funkcję setFocusBehavior()
dowolnie wiele razy przed zakończeniem obietnicy lub maksymalnie raz natychmiast po jej zrealizowaniu. Ostatnie wywołanie zastępuje wszystkie poprzednie wywołania.
A dokładniej:
– Zwrócona obietnica getDisplayMedia()
rozwiązuje się po wykonaniu mikrozadania. Wywołanie setFocusBehavior()
po zakończeniu tego mikrozadań powoduje zgłoszenie błędu.
– Wywoływanie połączenia setFocusBehavior()
dłużej niż sekundę od rozpoczęcia nagrywania jest w żaden sposób.
Oznacza to, że nie powiodą się oba te fragmenty kodu:
// 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");
Wywołanie setFocusBehavior()
powoduje też:
- ścieżka wideo strumienia zwrócona przez użytkownika
getDisplayMedia()
nie jest „live”. - po zwróceniu obietnicy
getDisplayMedia()
, jeśli użytkownik udostępnił ekran (a nie kartę lub okno).
Przykład
Aby wypróbować funkcję koncentracji warunkowej, uruchom wersję demonstracyjną aplikacji Glitch. Koniecznie zapoznaj się z kodem źródłowym.
Wykrywanie cech
Aby sprawdzić, czy CaptureController.setFocusBehavior()
jest obsługiwany, użyj polecenia:
if (
"CaptureController" in window &&
"setFocusBehavior" in CaptureController.prototype
) {
// CaptureController.setFocusBehavior() is supported.
}
Prześlij opinię
Zespół Chrome i społeczność ds. standardów internetowych chcą dowiedzieć się więcej o Twoich doświadczeniach związanych z fokusem warunkowym.
Opowiedz nam o projekcie
Czy jest coś, co w skupieniu warunkowym nie działa zgodnie z oczekiwaniami? A może brakuje Ci metod lub właściwości, które pozwolą Ci zrealizować Twój pomysł? Masz pytanie lub komentarz na temat modelu zabezpieczeń?
- Zgłoś problem ze specyfikacją w repozytorium GitHub lub opisz swój problem.
Problem z implementacją?
Czy wystąpił błąd z implementacją Chrome? Czy implementacja różni się od specyfikacji?
- Zgłoś błąd na https://new.crbug.com. Postaraj się podać jak najwięcej szczegółów oraz proste instrukcje odtwarzania filmu. Usterka dobrze sprawdza się w przypadku udostępniania kodu.
Pokaż wsparcie
Czy zamierzasz zastosować fokus warunkowy? Twoja publiczna pomoc pomaga zespołowi Chrome ustalać priorytety funkcji i pokazywać innym dostawcom przeglądarek, jak ważne jest, aby wspierać te funkcje.
Wyślij tweeta na adres @ChromiumDev, aby poinformować nas, gdzie i jak go używasz.
Przydatne linki
Podziękowania
Baner powitalny: Elena Taranenko.
Dziękujemy Rachelowi Andrew za przeczytanie tego artykułu.