Chrome 66 umożliwia stronom internetowym korzystanie z dodatkowego wyświetlacza za pomocą interfejsu Presentation API oraz kontrolowanie jego zawartości za pomocą interfejsu Presentation Receiver API.
Tło
Do tej pory deweloperzy internetowi mogli tworzyć treści, w których użytkownik widzi w Chrome treści lokalne inne niż te, które widzi na zewnętrznym wyświetlaczu, a nadal może kontrolować te treści lokalnie. Przykłady takich działań to zarządzanie kolejką odtwarzania na stronie youtube.com podczas odtwarzania filmów na telewizorze lub wyświetlanie prezentacji z notatkami na laptopie podczas wyświetlania prezentacji na pełnym ekranie w sesji Hangout.
Czasami jednak użytkownicy chcą po prostu wyświetlić treści na drugim, podłączonym ekranie. Wyobraź sobie na przykład użytkownika w sali konferencyjnej wyposażonej w projektor, z którym jest połączony za pomocą kabla HDMI. Zamiast dublować prezentację na zdalnym urządzeniu końcowym, użytkownik chce wyświetlić slajdy na pełnym ekranie projektora, pozostawiając ekran laptopa do wyświetlania notatek i sterowania slajdami. Autor strony może udostępnić tę funkcję w bardzo prymitywny sposób (np. wyświetlając nowe okno, które użytkownik musi ręcznie przeciągnąć na dodatkowy wyświetlacz i zmaksymalizować do pełnego ekranu), ale jest to kłopotliwe i nie zapewnia spójnego środowiska podczas prezentacji lokalnej i zdalnej.
Prezentowanie strony
Pokażę Ci, jak za pomocą interfejsu Presentation API wyświetlić stronę internetową na dodatkowym ekranie. Wynik końcowy jest dostępny na stronie https://googlechrome.github.io/samples/presentation-api/.
Najpierw utworzymy nowy obiekt PresentationRequest
, który będzie zawierać adres URL, który chcemy wyświetlać na dodatkowym 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);
});
Wyświetlenie promptu wyświetlania prezentacji wymaga od użytkownika wykonania czynności, takiej jak kliknięcie przycisku. Zatem wywołajmy funkcję presentationRequest.start()
po kliknięciu przycisku i poczekajmy, aż obietnica zostanie spełniona, gdy użytkownik wybierze wyświetlacz prezentacji (np. dodatkowy podłączony wyświetlacz 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 wyświetlana użytkownikowi może też zawierać odległe punkty końcowe, takie jak Chromecasty, jeśli jesteś połączony z siecią reklamującą te urządzenia. Pamiętaj, że wyświetlacze z odbiciem lustrzanym nie są uwzględniane na liście. Zobacz http://crbug.com/840466.
Gdy obietnica zostanie spełniona, wybrany wyświetlacz wyświetli stronę internetową pod adresem URL obiektu PresentationRequest
. Et voilà!
Możemy teraz przejść dalej i monitorować zdarzenia „close” (zamknięcie) i „terminate” (zakończenie), jak pokazano poniżej. Pamiętaj, że można ponownie połączyć „zamknięty” obiekt presentationConnection
z obiektem 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.');
});
Kontakt z tą stroną
Teraz myślisz sobie: „To fajne, ale jak mogę przekazywać wiadomości między stroną kontrolera (która została właśnie utworzona) a stroną odbiorcy (która została przekazana do obiektu PresentationRequest
)?”.
Najpierw pobierz istniejące połączenia na stronie odbiorcy za pomocą funkcjinavigator.presentation.receiver.connectionList
i nasłuchuj przychodzące połączenia, 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 otrzymujące wiadomość powoduje wywołanie zdarzenia „message”, na które możesz się zarejestrować.
Wiadomość może być ciągiem znaków, obiektem Blob, tablicą ArrayBuffer lub obiektem ArrayBufferView.
Wystarczy wywołać funkcję connection.send(message)
na stronie kontrolera lub stronie odbiornika.
// Controller page
function onSendMessageButtonClick() {
presentationConnection.send('Hello!');
}
presentationConnection.addEventListener('message', function(event) {
console.log('I just received ' + event.data + ' from the receiver.');
});
Aby poznać działanie interfejsu API, wypróbuj przykładowy projekt na stronie https://googlechrome.github.io/samples/presentation-api/. Mam nadzieję, że spodoba Ci się to tak samo jak mnie.
Sample i wersje demonstracyjne
Zapoznaj się z oficjalnym przykładem kodu Chrome, którego użyliśmy w tym artykule.
Polecam też interaktywne demo Photowall. Ta aplikacja internetowa umożliwia wielu kontrolerom wspólne wyświetlanie pokazu slajdów na ekranie prezentera. Kod jest dostępny pod adresem https://github.com/GoogleChromeLabs/presentation-api-samples.
Jeszcze jedno
Chrome ma menu „Cast”, które użytkownicy mogą wywołać w dowolnym momencie podczas wizyty w witrynie. Jeśli chcesz kontrolować domyślną prezentację 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ę odbiorcy i przeprowadzić jej debugowanie, otwórz wewnętrzną stronę chrome://inspect
, wybierz „Inne” i kliknij link „Sprawdź” obok aktualnie wyświetlanego adresu URL.
Warto też zapoznać się z informacjami na wewnętrznej stronie chrome://media-router-internals
, aby dowiedzieć się więcej o procesach wyszukiwania i dostępności.
Co dalej?
Od wersji 66 Chrome obsługuje platformy ChromeOS, Linux i Windows. Wsparcie dla użytkowników Mac będzie dostępne w późniejszym terminie.
Zasoby
- Stan funkcji w 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