Chrome 66 permet aux pages Web d'utiliser un écran associé secondaire via l'API Presentation et de contrôler son contenu via l'API Presentation Receiver.
Contexte
Jusqu'à présent, les développeurs Web pouvaient créer des expériences dans lesquelles un utilisateur voyait un contenu local dans Chrome qui était différent de celui qu'il verrait sur un écran distant, tout en pouvant contrôler cette expérience localement. Par exemple, vous pouvez gérer une file d'attente de lecture sur youtube.com pendant la lecture de vidéos sur un téléviseur ou regarder un diaporama avec des notes sur un ordinateur portable pendant la présentation en plein écran dans une session Hangout.
Cependant, il peut arriver que les utilisateurs souhaitent simplement présenter du contenu sur un deuxième écran associé. Par exemple, imaginons un utilisateur dans une salle de conférence équipée d'un projecteur auquel il est connecté via un câble HDMI. Plutôt que de dupliquer la présentation sur un point de terminaison distant, l'utilisateur souhaite vraiment présenter les diapositives en plein écran sur le projecteur, laissant l'écran de l'ordinateur portable disponible pour les notes du présentateur et le contrôle des diapositives. Bien que l'auteur du site puisse prendre en charge cette fonctionnalité de manière très rudimentaire (par exemple, en ouvrant une nouvelle fenêtre que l'utilisateur doit ensuite faire glisser manuellement vers l'écran secondaire et maximiser en plein écran), cette méthode est fastidieuse et offre une expérience incohérente entre la présentation locale et à distance.
Présenter une page
Je vais vous expliquer comment utiliser l'API Presentation pour présenter une page Web sur votre écran secondaire associé. Le résultat final est disponible à l'adresse https://googlechrome.github.io/samples/presentation-api/.
Tout d'abord, nous allons créer un objet PresentationRequest
qui contiendra l'URL que nous souhaitons présenter sur l'écran secondaire associé.
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);
});
L'affichage d'une invite d'affichage de présentation nécessite un geste de l'utilisateur, par exemple un clic sur un bouton. Appelons donc presentationRequest.start()
lors d'un clic sur un bouton et attendons que la promesse soit résolue une fois que l'utilisateur a sélectionné un écran de présentation (par exemple, un écran secondaire associé dans notre cas d'utilisation).
function onPresentButtonClick() {
presentationRequest.start()
.then(connection => {
console.log('Connected to ' + connection.url + ', id: ' + connection.id);
})
.catch(error => {
console.log(error);
});
}
La liste présentée à l'utilisateur peut également inclure des points de terminaison distants tels que des appareils Chromecast si vous êtes connecté à un réseau qui les fait la promotion. Notez que les écrans en mode miroir ne figurent pas dans la liste. Consultez la page http://crbug.com/840466.
Lorsque la promesse est résolue, la page Web à l'URL de l'objet PresentationRequest
est présentée à l'écran choisi. Et voilà !
Nous pouvons maintenant aller plus loin et surveiller les événements de fermeture et d'arrêt, comme indiqué ci-dessous. Notez qu'il est possible de se reconnecter à un presentationConnection
"fermé" avec presentationRequest.reconnect(presentationId)
, où presentationId
correspond à l'ID de l'objet presentationRequest
précédent.
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.');
});
Communiquer avec la page
Vous vous demandez peut-être comment transmettre des messages entre la page de contrôleur (celle que nous venons de créer) et la page du destinataire (celle que nous avons transmise à l'objet PresentationRequest
).
Tout d'abord, récupérons les connexions existantes sur la page du destinataire avec navigator.presentation.receiver.connectionList
et écoutons les connexions entrantes, comme illustré ci-dessous.
// 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);
});
}
Une connexion qui reçoit un message déclenche un événement "message" que vous pouvez écouter.
Le message peut être une chaîne, un Blob, un ArrayBuffer ou une ArrayBufferView.
Pour l'envoyer, il vous suffit d'appeler connection.send(message)
à partir de la page de la manette ou de la page du récepteur.
// Controller page
function onSendMessageButtonClick() {
presentationConnection.send('Hello!');
}
presentationConnection.addEventListener('message', function(event) {
console.log('I just received ' + event.data + ' from the receiver.');
});
Essayez l'exemple sur https://googlechrome.github.io/samples/presentation-api/ pour comprendre son fonctionnement. Je suis sûr que vous l'apprécierez autant que moi.
Exemples et démonstrations
Consultez l'exemple officiel de Chrome que nous avons utilisé pour cet article.
Je vous recommande également de regarder la démonstration interactive du mur d'images. Cette application Web permet à plusieurs contrôleurs de présenter un diaporama photo en collaboration sur un écran de présentation. Le code est disponible sur https://github.com/GoogleChromeLabs/presentation-api-samples.
Une dernière chose
Chrome dispose d'un menu de navigation "Cast" que les utilisateurs peuvent appeler à tout moment lorsqu'ils consultent un site Web. Si vous souhaitez contrôler la présentation par défaut de ce menu, attribuez navigator.presentation.defaultRequest
à un objet presentationRequest
personnalisé créé précédemment.
// Make this presentation the default one when using the "Cast" browser menu.
navigator.presentation.defaultRequest = presentationRequest;
Conseils pour les développeurs
Pour inspecter la page du récepteur et la déboguer, accédez à la page chrome://inspect
interne, sélectionnez "Autre", puis cliquez sur le lien "Inspecter" à côté de l'URL actuellement présentée.
Vous pouvez également consulter la page interne chrome://media-router-internals
pour en savoir plus sur les processus de découverte/disponibilité internes.
Étape suivante
Depuis Chrome 66, les plates-formes ChromeOS, Linux et Windows sont compatibles. La prise en charge sur Mac sera disponible plus tard.
Ressources
- État des fonctionnalités Chrome: https://www.chromestatus.com/features#presentation%20api
- Bugs d'implémentation: https://crbug.com/?q=component:Blink>PresentationAPI
- Spécification de l'API Presentation: https://w3c.github.io/presentation-api/
- Problèmes de spécification: https://github.com/w3c/presentation-api/issues