Chrome 66 consente alle pagine web di utilizzare un display secondario collegato tramite l'API Presentation e di controllarne i contenuti tramite l'API Presentation Receiver.
Sfondo
Fino a ora, gli sviluppatori web potevano creare esperienze in cui un utente visualizzava contenuti locali in Chrome diversi da quelli che vedeva su un display remoto, pur essendo in grado di controllare l'esperienza localmente. Alcuni esempi sono la gestione di una coda di riproduzione su youtube.com mentre i video vengono riprodotti sulla TV o la visualizzazione di un carosello di diapositive con le note dell'oratore su un laptop mentre la presentazione viene mostrata a schermo intero in una sessione di Hangout.
Esistono però scenari in cui gli utenti potrebbero semplicemente voler presentare i contenuti su un secondo display collegato. Ad esempio, immagina un utente in una sala conferenze con un proiettore a cui è collegato tramite un cavo HDMI. Invece di eseguire il mirroring della presentazione su un endpoint remoto, l'utente vuole davvero presentare le diapositive a schermo intero sul proiettore, lasciando lo schermo del laptop disponibile per le note dell'altoparlante e il controllo delle diapositive. Sebbene l'autore del sito possa supportare questa funzionalità in modo molto rudimentale (ad es. aprendo una nuova finestra che l'utente deve trascinare manualmente sul display secondario e massimizzare per visualizzarla a schermo intero), questa operazione è complicata e offre un'esperienza incoerente tra la presentazione locale e quella remota.
Presentare una pagina
Ti mostrerò come utilizzare l'API Presentation per presentare una pagina web sul display secondario collegato. Il risultato finale è disponibile all'indirizzo https://googlechrome.github.io/samples/presentation-api/.
Per prima cosa, creeremo un nuovo oggetto PresentationRequest
che conterrà l'URL che vogliamo presentare sul display secondario collegato.
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);
});
La visualizzazione di una richiesta di visualizzazione della presentazione richiede un gesto dell'utente, ad esempio un clic su un pulsante. Chiamiamo presentationRequest.start()
al clic di un pulsante e
aspettiamo che la promessa venga risolta quando l'utente ha selezionato un display
per la presentazione (ad es. un display secondario collegato nel nostro caso d'uso).
function onPresentButtonClick() {
presentationRequest.start()
.then(connection => {
console.log('Connected to ' + connection.url + ', id: ' + connection.id);
})
.catch(error => {
console.log(error);
});
}
L'elenco presentato all'utente può includere anche endpoint remoti come i dispositivi Chromecast, se sei connesso a una rete che li pubblicizza. Tieni presente che i display con mirroring non sono inclusi nell'elenco. Visita la pagina http://crbug.com/840466.
Quando la promessa viene risolta, la pagina web all'URL dell'oggetto PresentationRequest
viene presentata al display scelto. Et voilà!
Ora possiamo fare un passo avanti e monitorare gli eventi "close" e "terminate" come mostrato di seguito. Tieni presente che è possibile ricollegarsi a un presentationConnection
"chiuso" con presentationRequest.reconnect(presentationId)
, dove presentationId
è l'ID dell'oggetto presentationRequest
precedente.
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.');
});
Comunicare con la pagina
Ora ti starai chiedendo, è bello, ma come faccio a passare i messaggi tra la mia pagina di controllo (quella che abbiamo appena creato) e la pagina del destinatario (quella che abbiamo passato all'oggetto PresentationRequest
)?
Per prima cosa, recuperiamo le connessioni esistenti nella pagina del ricevitore connavigator.presentation.receiver.connectionList
e ascoltiamo le connessioni in entrata come mostrato di seguito.
// 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);
});
}
Una connessione che riceve un messaggio attiva un evento "message" che puoi ascoltare.
Il messaggio può essere una stringa, un Blob, un ArrayBuffer o un ArrayBufferView.
Per inviarlo, è sufficiente chiamare connection.send(message)
dalla pagina del controller o dalla pagina del destinatario.
// Controller page
function onSendMessageButtonClick() {
presentationConnection.send('Hello!');
}
presentationConnection.addEventListener('message', function(event) {
console.log('I just received ' + event.data + ' from the receiver.');
});
Prova l'esempio all'indirizzo https://googlechrome.github.io/samples/presentation-api/ per farti un'idea di come funziona. Sicuramente ti piacerà tanto quanto piace a me.
Samples e demo
Dai un'occhiata all'esempio ufficiale di Chrome che abbiamo utilizzato per questo articolo.
Ti consiglio anche di provare la demo interattiva della bacheca di foto. Questa app web consente a più controller di presentare in collaborazione una presentazione di foto su un display per le presentazioni. Il codice è disponibile all'indirizzo https://github.com/GoogleChromeLabs/presentation-api-samples.
Un'ultima cosa
Chrome ha un menu del browser "Trasmetti" che gli utenti possono richiamare in qualsiasi momento mentre visitano un sito web. Se vuoi controllare la presentazione predefinita di questo menu, assegnate navigator.presentation.defaultRequest
a un oggetto presentationRequest
personalizzato creato in precedenza.
// Make this presentation the default one when using the "Cast" browser menu.
navigator.presentation.defaultRequest = presentationRequest;
Suggerimenti per i dev
Per ispezionare la pagina del destinatario ed eseguire il debug, vai alla pagina internachrome://inspect
, seleziona "Altro" e fai clic sul link "Ispeziona" accanto all'URL attualmente visualizzato.
Ti consigliamo inoltre di consultare la pagina chrome://media-router-internals
interna per approfondire le procedure di rilevamento/disponibilità interne.
Passaggi successivi
A partire da Chrome 66, sono supportate le piattaforme ChromeOS, Linux e Windows. Il supporto per Mac sarà disponibile in un secondo momento.
Risorse
- Stato delle funzionalità di Chrome: https://www.chromestatus.com/features#presentation%20api
- Bug di implementazione: https://crbug.com/?q=component:Blink>PresentationAPI
- Specifica dell'API Presentation: https://w3c.github.io/presentation-api/
- Problemi relativi alle specifiche: https://github.com/w3c/presentation-api/issues