Présenter des pages Web sur des écrans associés secondaires

François Beaufort
François Beaufort

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 PresentationReceiver.

1/2 L'utilisateur choisit un écran associé secondaire
1/2. L'utilisateur choisit un écran associé secondaire
2/2. Une page Web s'affiche automatiquement sur l'écran sélectionné précédemment
2/2. Une page Web s'affiche automatiquement sur l'écran sélectionné précédemment

Contexte

Jusqu'à présent, les développeurs Web pouvaient créer des expériences dans lesquelles un utilisateur voyait dans Chrome un contenu local différent de celui affiché sur un écran distant, tout en continuant à 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 le téléviseur, ou afficher une vidéo de diapositives avec les commentaires du présentateur sur un ordinateur portable alors que la présentation en plein écran est affichée dans une session Hangouts.

Toutefois, dans certains cas, les utilisateurs peuvent simplement vouloir présenter du contenu sur un deuxième écran connecté. Par exemple, imaginez 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, en laissant l'écran de l'ordinateur portable disponible pour les commentaires 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 l'afficher en plein écran), elle est fastidieuse et incohérente entre la présentation en local et à distance.

Présenter une page

Voyons comment utiliser l'API Presentation pour présenter une page Web sur votre écran associé secondaire. 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 à afficher sur l'écran associé secondaire.

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, comme 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 affichage de présentation (par exemple, un écran associé secondaire 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 diffuse. Notez que les écrans dupliqués ne figurent pas dans la liste. Consultez la page http://crbug.com/840466.

Sélecteur d&#39;affichage de présentation
Sélecteur d'affichage de présentation

Lorsque la promesse est résolue, la page Web correspondant à l'URL de l'objet PresentationRequest est présentée à l'affichage 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

C'est bien, mais comment transmettre des messages entre ma page de contrôleur (celle que nous venons de créer) et la page de destination (celle que nous avons transmise à l'objet PresentationRequest) ?

Tout d'abord, récupérons les connexions existantes sur la page du récepteur avec navigator.presentation.receiver.connectionList et écoutons les connexions entrantes comme indiqué 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 recevant un message déclenche un événement "message" que vous pouvez écouter. Le message peut être une chaîne, un objet Blob, un objet ArrayBuffer ou un ArrayBufferView. Pour l'envoyer, il suffit d'appeler connection.send(message) depuis la page du contrôleur ou la page de destination.

// Controller page

function onSendMessageButtonClick() {
  presentationConnection.send('Hello!');
}

presentationConnection.addEventListener('message', function(event) {
  console.log('I just received ' + event.data + ' from the receiver.');
});

Testez l'exemple disponible à l'adresse https://googlechrome.github.io/samples/presentation-api/ pour vous faire une idée du fonctionnement. Je suis sûr que vous apprécierez cela autant que moi.

Exemples et démonstrations

Découvrez l'exemple Chrome officiel que nous avons utilisé pour cet article.

Je vous recommande également la démonstration interactive de Photowall. Cette application Web permet à plusieurs contrôleurs de présenter de manière collaborative un diaporama de photos sur un écran de présentation. Le code est disponible à l'adresse https://github.com/GoogleChromeLabs/presentation-api-samples.

Capture d&#39;écran de la démo sur le mur de photos
Photo par José Luis Mieza / CC BY-NC-SA 2.0

Une dernière chose

Chrome propose 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 de développement

Pour inspecter la page du destinataire 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 affichée.

Inspecter les pages de destination de la présentation
Inspecter les pages de destination de la présentation

Vous pouvez également consulter la page chrome://media-router-internals interne pour découvrir les processus internes de découverte/disponibilité.

Étapes suivantes

Depuis Chrome 66, les plates-formes ChromeOS, Linux et Windows sont compatibles. La compatibilité Mac sera disponible plus tard.

Ressources