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.
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 w 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 wyświetlaczu. 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 podłączonym wyświetlaczu. 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 jakiegoś działania, np. kliknięcia 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 tej listy nie ma na wyświetlaczu lustrzanym. 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ć się z „zamkniętym” obiektem presentationConnection
za pomocą obiektu 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.');
});
Kontaktowanie się ze stroną
Wygląda to dobrze, ale jak przekazywać wiadomości między moją 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, 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, wypróbuj przykładowy projekt dostępny na stronie https://googlechrome.github.io/samples/presentation-api/. Na pewno spodoba Ci się tak jak mi.
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 na stronie 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.
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 66 przeglądarki Chrome obsługuje systemy 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