Udostępnianie kart, okien i ekranów na platformie internetowej jest już możliwe dzięki interfejsowi Screen Capture API. Gdy aplikacja internetowa wywołuje getDisplayMedia()
, Chrome prosi użytkownika o udostępnienie aplikacji internetowej karty, okna lub ekranu jako filmu MediaStreamTrack
.
Wiele aplikacji internetowych korzystających z getDisplayMedia()
wyświetla użytkownikowi podgląd nagranej powierzchni. Na przykład aplikacje do rozmów wideo często przesyłają ten film strumieniowo do zdalnych użytkowników, jednocześnie renderując go na lokalnym urządzeniu HTMLVideoElement
, dzięki czemu lokalny użytkownik może stale widzieć podgląd tego, co udostępniają.
W tej dokumentacji opisujemy nowy interfejs Captured Surface Control API w Chrome, który umożliwia aplikacji internetowej przewijanie przechwyconej karty oraz odczytywanie i zapisywanie poziomu powiększenia przechwyconej karty.
Dlaczego warto korzystać z funkcji kontroli powierzchni rejestrowanej?
Wszystkie aplikacje do rozmów wideo mają tę samą wadę: jeśli użytkownik chce wejść w interakcję z przechwyconą kartą lub oknem, musi przełączyć się na tę platformę, aby odsunąć go od aplikacji do rozmów wideo. Wiąże się to z pewnymi wyzwaniami:
- Użytkownik nie może jednocześnie zobaczyć zarejestrowanej aplikacji oraz filmów użytkowników zdalnych, chyba że użyje funkcji Obraz w obrazie lub osobnych okien obok siebie dla karty Rozmowy wideo i karty udostępnionej. Na mniejszym ekranie może to być trudne.
- Użytkownik jest zmęczony koniecznością przełączania się między aplikacją do rozmów wideo a rejestrowaną powierzchnią.
- Użytkownik traci dostęp do elementów sterujących aplikacji do rozmów wideo, gdy nie znajduje się w jego pobliżu. na przykład umieszczonej aplikacji do czatu, emotikonów, powiadomień o użytkownikach proszących o dołączenie do rozmowy, sterowania multimediami i układem oraz inne przydatne funkcje rozmów wideo.
- Osoba prowadząca nie może przekazać kontroli uczestnikom zdalnym. Prowadzi to do dobrze znanej sytuacji, w której użytkownicy zdalni proszą prowadzącego o zmianę slajdu, przesunięcie trochę w górę lub w dół albo dostosowanie poziomu powiększenia.
Interfejs Captured Surface Control API rozwiązuje te problemy.
Jak korzystać z przechwyconej kontroli powierzchni?
Użycie funkcji Capture Surface Control wymaga wykonania kilku czynności, na przykład bezpośredniego przechwycenia karty przeglądarki i uzyskania zgody użytkownika przed jej przewinięciem i powiększeniem.
Przechwytywanie karty przeglądarki
Najpierw poproś użytkownika o wybranie platformy do udostępnienia za pomocą getDisplayMedia()
, a następnie powiąż obiekt CaptureController
z sesją przechwytywania. Będziemy używać tego obiektu do sterowania przechwyconą powierzchnią.
const controller = new CaptureController();
const stream = await navigator.mediaDevices.getDisplayMedia({ controller });
Następnie utwórz lokalny podgląd zarejestrowanej powierzchni w postaci elementu <video>
:
const previewTile = document.querySelector('video');
previewTile.srcObject = stream;
Jeśli użytkownik zdecyduje się udostępnić okno lub ekran, aktualnie wykracza to poza zakres dostępu. Jeśli jednak postanowił udostępnić kartę, możemy kontynuować.
const [track] = stream.getVideoTracks();
if (track.getSettings().displaySurface !== 'browser') {
// Bail out early if the user didn't pick a tab.
return;
}
Prośba o zgodę
Pierwsze wywołanie metody sendWheel()
lub setZoomLevel()
dla danego obiektu CaptureController
powoduje wyświetlenie prośby o przyznanie uprawnień. Jeśli użytkownik przyzna odpowiednie uprawnienia, dozwolone są kolejne wywołania tych metod w obiekcie CaptureController
. Jeśli użytkownik odmówi zgody, zwrócona obietnica zostanie odrzucona.
Pamiętaj, że obiekty CaptureController
są jednoznacznie powiązane z konkretną capture-session, nie mogą być powiązane z inną sesją przechwytywania ani nie przeżyć po zmianie strony, na której zostały zdefiniowane. Sesje przechwytywania zachowują jednak ważność po poruszaniu się po przechwyconej stronie.
Aby wyświetlić prośbę o przyznanie uprawnień, wymagany jest gest użytkownika. Tylko połączenia sendWheel()
i setZoomLevel()
wymagają gestu użytkownika i tylko wtedy, gdy trzeba pokazać prośbę. jeśli użytkownik kliknie przycisk powiększania lub pomniejszania w aplikacji internetowej, wyświetli się gest tego użytkownika; ale jeśli aplikacja chce najpierw zaoferować sterowanie przewijaniem, deweloperzy powinni pamiętać, że przewijanie nie jest gestem użytkownika. Jedną z możliwości jest zaoferowanie użytkownikowi „rozpoczęcia przewijania”, zgodnie z poniższym przykładem:
const startScrollingButton = document.querySelector('button');
startScrollingButton.addEventListener('click', async () => {
try {
const noOpWheelAction = {};
await controller.sendWheel(noOpWheelAction);
// The user approved the permission prompt.
// You can now scroll and zoom the captured tab as shown later in the article.
} catch (error) {
return; // Permission denied. Bail.
}
});
Przewiń
Dzięki funkcji sendWheel()
aplikacja do przechwytywania może wyświetlać zdarzenia obrotowe o wybranej wielkości przez wybrane współrzędne w widocznym obszarze karty. Zdarzenia nie da się odróżnić od zarejestrowanej aplikacji od bezpośredniej interakcji użytkownika.
Zakładając, że aplikacja do przechwytywania ruchu wykorzystuje element <video>
o nazwie "previewTile"
, poniższy kod pokazuje, jak przekazywać zdarzenia wysyłane kołami do przechwyconych kart:
const previewTile = document.querySelector('video');
previewTile.addEventListener('wheel', async (event) => {
// Translate the offsets into coordinates which sendWheel() can understand.
// The implementation of this translation is explained further below.
const [x, y] = translateCoordinates(event.offsetX, event.offsetY);
const [wheelDeltaX, wheelDeltaY] = [-event.deltaX, -event.deltaY];
try {
// Relay the user's action to the captured tab.
await controller.sendWheel({ x, y, wheelDeltaX, wheelDeltaY });
} catch (error) {
// Inspect the error.
// ...
}
});
Metoda sendWheel()
wykorzystuje słownik z 2 zbiorami wartości:
x
iy
: współrzędne miejsca, w którym ma być dostarczone zdarzenie koła.wheelDeltaX
iwheelDeltaY
: siła przewijania (w pikselach) odpowiednio do przewijania w poziomie i w pionie. Pamiętaj, że te wartości są odwrócone w porównaniu z pierwotnym zdarzeniem koła.
Oto możliwa implementacja translateCoordinates()
:
function translateCoordinates(offsetX, offsetY) {
const previewDimensions = previewTile.getBoundingClientRect();
const trackSettings = previewTile.srcObject.getVideoTracks()[0].getSettings();
const x = trackSettings.width * offsetX / previewDimensions.width;
const y = trackSettings.height * offsetY / previewDimensions.height;
return [Math.floor(x), Math.floor(y)];
}
Zwróć uwagę, że w wcześniejszym kodzie występują trzy różne rozmiary:
- Rozmiar elementu
<video>
. - Rozmiar przechwyconych klatek (przedstawiony jako
trackSettings.width
itrackSettings.height
). - Rozmiar karty.
Rozmiar elementu <video>
jest w całości w domenie aplikacji przechwytującej i nie jest znany przeglądarce. Rozmiar karty mieści się w całej domenie przeglądarki i nie jest znany aplikacji internetowej.
Aplikacja internetowa używa właściwości translateCoordinates()
do przekształcania przesunięcia względem elementu <video>
na współrzędne w przestrzeni współrzędnych ścieżki wideo. Przeglądarka również dostosuje rozmiar zarejestrowanych klatek do rozmiaru karty i wyświetli zdarzenie przewijania z przesunięciem zgodnym z oczekiwaniami aplikacji internetowej.
Obietnica zwrócona przez funkcję sendWheel()
może zostać odrzucona w tych przypadkach:
- Sesja przechwytywania jeszcze się nie rozpoczęła lub już się zakończyła, w tym zatrzymanie asynchroniczne, gdy działanie
sendWheel()
jest obsługiwane przez przeglądarkę. - jeśli użytkownik nie przyznał aplikacji uprawnień do korzystania z narzędzia
sendWheel()
. - Jeśli aplikacja przechwytuje zdarzenie przewijania we współrzędnych, które są poza obszarem
[trackSettings.width, trackSettings.height]
. Pamiętaj, że te wartości mogą zmieniać się asynchronicznie, warto więc wychwycić i zignorować błąd. (Pamiętaj, że typ pola0, 0
zwykle nie znajduje się poza zakresem, więc można go bezpiecznie użyć, aby poprosić użytkownika o zgodę).
Zoom
Poziom powiększenia zarejestrowanej karty można dostosować za pomocą tych platform CaptureController
:
getSupportedZoomLevels()
zwraca listę poziomów powiększenia obsługiwanych przez przeglądarkę wyrażoną jako procent „domyślnego poziomu powiększenia”, który wynosi 100%. Ta lista rośnie monotonicznie i zawiera wartość 100.getZoomLevel()
zwraca bieżący poziom powiększenia karty.setZoomLevel()
ustawia poziom powiększenia karty na dowolną wartość całkowitą występującą w polugetSupportedZoomLevels()
i zwraca obietnicę, gdy operacja się uda. Pamiętaj, że poziom powiększenia nie jest resetowany na koniec sesji przechwytywania.oncapturedzoomlevelchange
umożliwia słuchanie zmian poziomu powiększenia zarejestrowanej karty, ponieważ użytkownicy mogą zmieniać poziom powiększenia z poziomu aplikacji do nagrywania lub przez bezpośrednią interakcję z otwartą kartą.
Połączenia z numerem setZoomLevel()
są ograniczone przez pozwolenie. inne metody powiększenia (tylko do odczytu) są „bezpłatne”, podobnie jak nasłuchiwanie zdarzeń.
Poniższy przykład pokazuje, jak zwiększyć poziom powiększenia zarejestrowanej karty w dotychczasowej sesji przechwytywania:
const zoomIncreaseButton = document.getElementById('zoomInButton');
zoomIncreaseButton.addEventListener('click', async (event) => {
const levels = CaptureController.getSupportedZoomLevels();
const index = levels.indexOf(controller.getZoomLevel());
const newZoomLevel = levels[Math.min(index + 1, levels.length - 1)];
try {
await controller.setZoomLevel(newZoomLevel);
} catch (error) {
// Inspect the error.
// ...
}
});
Poniższy przykład pokazuje reakcję na zmiany poziomu powiększenia na zarejestrowanej karcie:
controller.addEventListener('capturedzoomlevelchange', (event) => {
const zoomLevel = controller.getZoomLevel();
document.querySelector('#zoomLevelLabel').textContent = `${zoomLevel}%`;
});
Wykrywanie cech
Aby sprawdzić, czy wysyłanie zdarzeń kółka myszy jest obsługiwane, użyj polecenia:
if (!!window.CaptureController?.prototype.sendWheel) {
// CaptureController sendWheel() is supported.
}
Aby sprawdzić, czy sterowanie powiększeniem jest obsługiwane, użyj tych poleceń:
if (!!window.CaptureController?.prototype.setZoomLevel) {
// CaptureController setZoomLevel() is supported.
}
Włącz przechwyconą kontrolę powierzchni
Interfejs Captured Surface Control API jest dostępny w Chrome na komputery pod flagą Captured Surface Control i można go włączyć na stronie chrome://flags/#captured-surface-control
.
W ramach tej funkcji rozpoczyna się też wersja próbna origin Chrome 122 na komputery, dzięki której deweloperzy mogą włączyć tę funkcję dla użytkowników swoich witryn w celu zbierania danych od prawdziwych użytkowników. Więcej informacji o testowaniu origin i sposobie ich działania znajdziesz w artykule Pierwsze kroki z testowaniem origin.
Bezpieczeństwo i prywatność
Zasady dotyczące uprawnień "captured-surface-control"
pozwalają zarządzać dostępem aplikacji do przechwytywania i umieszczonych elementów iframe innych firm do przechwyconych informacji o platformie. Aby lepiej zrozumieć wady bezpieczeństwa, zapoznaj się z sekcją Uwagi dotyczące prywatności i bezpieczeństwa w wyjaśnieniu dotyczącym przechwytywania ekranu.
Prezentacja
Możesz wypróbować funkcję Captured Surface Control, uruchamiając wersję demonstracyjną aplikacji Glitch. Koniecznie zapoznaj się z kodem źródłowym.
Zmiany w porównaniu z poprzednimi wersjami Chrome
Oto kilka głównych różnic w działaniu rejestrowanych urządzeń kontroli powierzchni, o których trzeba pamiętać:
- W Chrome 124 i starszych wersjach:
- Uprawnienie (jeśli zostało przyznane) jest ograniczone do sesji przechwytywania powiązanej z danym elementem
CaptureController
, a nie do źródła przechwytywania.
- Uprawnienie (jeśli zostało przyznane) jest ograniczone do sesji przechwytywania powiązanej z danym elementem
- W Chrome 122:
getZoomLevel()
zwraca obietnicę przy bieżącym poziomie powiększenia karty.- Jeśli użytkownik nie przyznał aplikacji uprawnień do korzystania,
sendWheel()
zwraca obietnicę odrzucona z komunikatem o błędzie"No permission."
. Typ błędu to"NotAllowedError"
w Chrome 123 i nowszych wersjach. - Domena
oncapturedzoomlevelchange
jest niedostępna. Możesz użyć kodu polyfill za pomocąsetInterval()
.
Prześlij opinię
Zespół Chrome i społeczność zajmująca się standardami internetowymi chcą poznać Waszą opinię o funkcji Przechwycona kontrola powierzchni.
Opowiedz nam o projekcie
Czy jest coś, co w rejestrowanych obrazach powierzchni 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 instrukcje odtwarzania. Glitch doskonale sprawdza się w przypadku udostępniania odtwarzanych błędów.