In Chrome 66 können Webseiten über die Presentation API ein sekundär angeschlossenes Display verwenden und den Inhalt über die Presentation Receiver API steuern.
Hintergrund
Bisher konnten Webentwickler Umgebungen erstellen, in denen Nutzer lokale Inhalte in Chrome sehen, die sich von den Inhalten unterscheiden, die sie auf einem Remote-Display sehen, und diese Umgebung lokal steuern können. Beispiele hierfür sind die Verwaltung einer Wiedergabeliste auf youtube.com, während Videos auf dem Fernseher wiedergegeben werden, oder die Anzeige einer Foliensammlung mit Sprechernotizen auf einem Laptop, während die Präsentation im Vollbildmodus in einer Hangouts-Sitzung gezeigt wird.
Es gibt jedoch Szenarien, in denen Nutzer einfach Inhalte auf einem zweiten, angeschlossenen Display präsentieren möchten. Angenommen, ein Nutzer befindet sich in einem Konferenzraum mit einem Projektor, mit dem er über ein HDMI-Kabel verbunden ist. Anstatt die Präsentation auf einen Remote-Endpunkt zu spiegeln, möchte der Nutzer die Folien im Vollbildmodus auf dem Projektor präsentieren, sodass das Laptop-Display für Sprechernotizen und die Foliensteuerung zur Verfügung steht. Der Website-Entwickler könnte dies zwar auf sehr rudimentäre Weise unterstützen (z. B. durch das Aufpoppen eines neuen Fensters, das der Nutzer dann manuell auf das zweite Display ziehen und maximieren muss), aber das ist umständlich und führt zu einer inkonsistenten Darstellung zwischen lokaler und Remote-Präsentation.
Seiten präsentieren
Ich zeige Ihnen, wie Sie mit der Presentation API eine Webseite auf dem sekundär angeschlossenen Display anzeigen. Das Endergebnis ist unter https://googlechrome.github.io/samples/presentation-api/ verfügbar.
Zuerst erstellen wir ein neues PresentationRequest
-Objekt, das die URL enthält, die auf dem sekundär angehängten Bildschirm angezeigt werden soll.
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);
});
Damit eine Aufforderung zur Präsentationsanzeige angezeigt wird, ist eine Nutzergeste wie das Klicken auf eine Schaltfläche erforderlich. Rufen wir also presentationRequest.start()
bei einem Schaltflächenklick auf und warten, bis das Promise aufgelöst wird, sobald der Nutzer ein Präsentationsdisplay ausgewählt hat (z. B. ein sekundär angeschlossenes Display in unserem Anwendungsfall).
function onPresentButtonClick() {
presentationRequest.start()
.then(connection => {
console.log('Connected to ' + connection.url + ', id: ' + connection.id);
})
.catch(error => {
console.log(error);
});
}
Die Liste, die dem Nutzer angezeigt wird, kann auch Remote-Endpunkte wie Chromecast-Geräte enthalten, wenn Sie mit einem Netzwerk verbunden sind, in dem für diese geworben wird. Spiegelbilder sind nicht in der Liste enthalten. Weitere Informationen finden Sie unter http://crbug.com/840466.
Wenn die Zusicherung erfüllt ist, wird die Webseite unter der Objekt-URL PresentationRequest
auf dem ausgewählten Display angezeigt. Und voilà!
Wir können jetzt weitermachen und die Ereignisse „close“ und „terminate“ überwachen, wie unten dargestellt. Es ist möglich, eine neue Verbindung zu einem „geschlossenen“ presentationConnection
mit presentationRequest.reconnect(presentationId)
herzustellen. Dabei ist presentationId
die ID des vorherigen presentationRequest
-Objekts.
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.');
});
Mit der Seite kommunizieren
Jetzt denken Sie vielleicht: Das ist schön, aber wie übergebe ich Nachrichten zwischen meiner Controller-Seite (der Seite, die wir gerade erstellt haben) und der Empfängerseite (der Seite, die wir an das PresentationRequest
-Objekt übergeben haben)?
Rufen wir zuerst mit navigator.presentation.receiver.connectionList
vorhandene Verbindungen auf der Empfängerseite ab und hören wir auf eingehende Verbindungen, wie unten dargestellt.
// 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);
});
}
Wenn eine Verbindung eine Nachricht empfängt, wird das Ereignis „message“ ausgelöst, auf das Sie warten können.
Die Nachricht kann ein String, ein Blob, ein ArrayBuffer oder eine ArrayBufferView sein.
Zum Senden musst du einfach connection.send(message)
auf der Seite des Controllers oder des Empfängers aufrufen.
// Controller page
function onSendMessageButtonClick() {
presentationConnection.send('Hello!');
}
presentationConnection.addEventListener('message', function(event) {
console.log('I just received ' + event.data + ' from the receiver.');
});
Probieren Sie das Beispiel unter https://googlechrome.github.io/samples/presentation-api/ aus, um sich ein Bild davon zu machen, wie es funktioniert. Ich bin sicher, dass es Ihnen genauso gut gefallen wird wie mir.
Samples und Demos
Sehen Sie sich das offizielle Chrome-Beispiel an, das wir für diesen Artikel verwendet haben.
Ich empfehle auch die interaktive Demo für die Fotowand. Mit dieser Webanwendung können mehrere Controller gemeinsam eine Fotopräsentation auf einem Präsentationsbildschirm abspielen. Der Code ist unter https://github.com/GoogleChromeLabs/presentation-api-samples verfügbar.
Eine Sache noch
Chrome hat ein Browsermenü „Streamen“, das Nutzer jederzeit aufrufen können, wenn sie eine Website besuchen. Wenn Sie die Standardpräsentation für dieses Menü steuern möchten, weisen Sie navigator.presentation.defaultRequest
einem benutzerdefinierten presentationRequest
-Objekt zu, das Sie zuvor erstellt haben.
// Make this presentation the default one when using the "Cast" browser menu.
navigator.presentation.defaultRequest = presentationRequest;
Tipps für Entwickler
Wenn Sie die Empfängerseite prüfen und beheben möchten, rufen Sie die interne Seite chrome://inspect
auf, wählen Sie „Sonstiges“ aus und klicken Sie neben der aktuell angezeigten URL auf den Link „Prüfen“.
Auf der internen chrome://media-router-internals
Seite finden Sie weitere Informationen zu den internen Prozessen zur Entdeckung und Verfügbarkeit.
Nächste Schritte
Seit Chrome 66 werden die Plattformen ChromeOS, Linux und Windows unterstützt. Mac-Support wird später verfügbar sein.
Ressourcen
- Chrome-Funktionsstatus: https://www.chromestatus.com/features#presentation%20api
- Implementierungsfehler: https://crbug.com/?q=component:Blink>PresentationAPI
- Presentation API-Spezifikation: https://w3c.github.io/presentation-api/
- Probleme mit der Spezifikation: https://github.com/w3c/presentation-api/issues