Chrome 66 umożliwia stronom internetowym korzystanie z dodatkowego podłączonego wyświetlacza przez Presentation API oraz kontrolowanie jego zawartości za pomocą Presentation Receiver API.
Wprowadzenie
Do tej pory twórcy stron internetowych mogli tworzyć w Chrome środowisko, w którym użytkownicy widzieli w Chrome treści lokalne inne niż na wyświetlaczu zdalnym, zachowując jednocześnie możliwość lokalnego kontrolowania. Może to być na przykład zarządzanie kolejką odtwarzania na youtube.com podczas odtwarzania filmu na telewizorze lub wyświetlanie na laptopie rolki ze slajdami podczas sesji na Hangouts podczas wyświetlania na pełnym ekranie.
Istnieją jednak sytuacje, w których użytkownicy mogą po prostu zechcieć zaprezentować zawartość na drugim, dołączonym wyświetlaczu. Wyobraź sobie na przykład użytkownika w sali konferencyjnej wyposażonej w projektor, do którego jest podłączony kablem HDMI. Zamiast powielać prezentację w zdalnym punkcie końcowym, użytkownik chce wyświetlić slajdy na pełnym ekranie w projekcie, pozostawiając ekran laptopa na potrzeby notatek i elementów sterujących przesuwaniem. Wprawdzie autor strony radzi sobie z tym w bardzo praktyczny sposób (np. przez wyświetlenie nowego okna, które użytkownik musi ręcznie przeciągnąć na dodatkowy wyświetlacz i zmaksymalizować widok pełnoekranowy do pełnego ekranu), jednak jest to niewygodne i zapewnia niespójność pomiędzy prezentacjami lokalnymi i zdalnymi.
Prezentowanie strony
Omówię teraz sposób używania interfejsu Presentation API do prezentowania strony internetowej na dodatkowym monitorze. Efekt końcowy jest dostępny na stronie https://googlechrome.github.io/samples/presentation-api/.
Najpierw utworzymy nowy obiekt PresentationRequest
zawierający URL, który chcemy pokazać na dodatkowym, podłączonym wyświetlaczu.
const presentationRequest = new PresentationRequest('receiver.html');
In this article, I won’t cover use cases where the parameter passed to
`PresentationRequest` can be an array like `['cast://foo’, 'apple://foo',
'https://example.com']` as this is not relevant there.
We can now monitor presentation display availability and toggle a "Present"
button visibility based on presentation displays availability. Note that we can
also decide to always show this button.
<aside class="caution"><b>Caution:</b> The browser may use more energy while the <code>availability</code> object is alive
and actively listening for presentation display availability changes. Please
use it with caution in order to save energy on mobile.</aside>
```js
presentationRequest.getAvailability()
.then(availability => {
console.log('Available presentation displays: ' + availability.value);
availability.addEventListener('change', function() {
console.log('> Available presentation displays: ' + availability.value);
});
})
.catch(error => {
console.log('Presentation availability not supported, ' + error.name + ': ' +
error.message);
});
Aby pokazać prompt w widoku prezentacji, użytkownik musi wykonać gest, np. kliknąć przycisk. Wywołujmy więc presentationRequest.start()
kliknięciem przycisku i poczekamy, aż użytkownik wybierze wyświetlacz do prezentacji (np. dodatkowy wyświetlacz podłączany w naszym przypadku użycia).
function onPresentButtonClick() {
presentationRequest.start()
.then(connection => {
console.log('Connected to ' + connection.url + ', id: ' + connection.id);
})
.catch(error => {
console.log(error);
});
}
Lista prezentowana użytkownikowi może też zawierać zdalne punkty końcowe, takie jak urządzenia Chromecast, jeśli masz połączenie z reklamowaną siecią. Pamiętaj, że tej listy nie ma na ekranie lustrzanym. Zobacz http://crbug.com/840466.
Po spełnieniu obietnicy strona internetowa pod adresem URL obiektu PresentationRequest
jest przedstawiana wybranemu wyświetlaczowi. I gotowe!
Możemy teraz przejść dalej i monitorować zdarzenia „zamknięcia” i „zakończenia”, jak pokazano poniżej. Pamiętaj, że możesz ponownie połączyć się z „zamkniętym” obiektem presentationConnection
za pomocą presentationRequest.reconnect(presentationId)
, gdzie presentationId
to identyfikator poprzedniego obiektu presentationRequest
.
function onCloseButtonClick() {
// Disconnect presentation connection but will allow reconnection.
presentationConnection.close();
}
presentationConnection.addEventListener('close', function() {
console.log('Connection closed.');
});
function onTerminateButtonClick() {
// Stop presentation connection for good.
presentationConnection.terminate();
}
presentationConnection.addEventListener('terminate', function() {
console.log('Connection terminated.');
});
Komunikacja ze stroną
Wygląda to dobrze, ale jak przekazywać wiadomości między stroną kontrolera (którą właśnie utworzyliśmy) a stroną odbiorcy (tę, którą przekazaliśmy do obiektu PresentationRequest
)?
Najpierw pobierzmy dotychczasowe połączenia na stronie odbiorcy za pomocą usługi navigator.presentation.receiver.connectionList
i wsłuchajmy się w połączenia przychodzące, jak pokazano poniżej.
// Receiver page
navigator.presentation.receiver.connectionList
.then(list => {
list.connections.map(connection => addConnection(connection));
list.addEventListener('connectionavailable', function(event) {
addConnection(event.connection);
});
});
function addConnection(connection) {
connection.addEventListener('message', function(event) {
console.log('Message: ' + event.data);
connection.send('Hey controller! I just received a message.');
});
connection.addEventListener('close', function(event) {
console.log('Connection closed!', event.reason);
});
}
Połączenie odbierające wiadomość uruchamia zdarzenie „wiadomość”, którą możesz nasłuchiwać.
Wiadomość może być ciągiem znaków, obiektem Blob, SlateBuffer lub ArrayBufferView.
Aby wysłać wiadomość, wystarczy wywołać funkcję connection.send(message)
ze strony kontrolera lub odbiorcy.
// Controller page
function onSendMessageButtonClick() {
presentationConnection.send('Hello!');
}
presentationConnection.addEventListener('message', function(event) {
console.log('I just received ' + event.data + ' from the receiver.');
});
Wypróbuj przykład na stronie https://googlechrome.github.io/samples/presentation-api/, aby zobaczyć, jak działa. Na pewno spodoba Ci się tak jak mi.
Sample i wersje demonstracyjne
Zobacz oficjalną próbkę Chrome, której użyliśmy w tym artykule.
Zalecamy też prezentację interaktywnej ściany Photowall. Ta aplikacja internetowa pozwala wielu kontrolerom na wspólne wyświetlanie pokazu slajdów ze zdjęć na wyświetlaczu. Kod jest dostępny na stronie https://github.com/GoogleChromeLabs/presentation-api-samples.
Jeszcze jedno
Chrome ma menu „Przesyłanie”, które użytkownicy mogą w dowolnej chwili wywołać podczas odwiedzania strony. Jeśli chcesz kontrolować domyślną prezentację dla tego menu, przypisz navigator.presentation.defaultRequest
do utworzonego wcześniej niestandardowego obiektu presentationRequest
.
// Make this presentation the default one when using the "Cast" browser menu.
navigator.presentation.defaultRequest = presentationRequest;
Wskazówki dla programistów
Aby sprawdzić stronę odbiornika i ją zdebugować, wejdź na stronę wewnętrzną chrome://inspect
, wybierz „Inne” i kliknij link „Sprawdź” obok wyświetlanego adresu URL.
Więcej informacji o wewnętrznych procesach wykrywania i dostępności znajdziesz na wewnętrznej stronie chrome://media-router-internals
.
Co dalej
Od wersji Chrome 66 obsługiwane są platformy ChromeOS, Linux i Windows. Obsługa Maców zostanie udostępniona później.
Zasoby
- Stan funkcji Chrome: https://www.chromestatus.com/features#presentation%20api
- Błędy implementacji: https://crbug.com/?q=component:Blink>PresentationAPI
- Specyfikacja interfejsu Presentation API: https://w3c.github.io/presentation-api/
- Problemy ze specyfikacją: https://github.com/w3c/presentation-api/issues