在次要附加的螢幕上顯示網頁

法蘭索瓦博福
François Beaufort

Chrome 66 允許網頁透過 Presentation API 使用次要連接的螢幕,並透過 PresentationReceiver API 控管內容。

1/2. 使用者選擇次要連接的螢幕
1/2. 使用者選擇次要連接的螢幕
2/2。網頁自動顯示在先前選取的畫面
2/2. 網頁會自動顯示在先前選取的螢幕畫面上

背景

在此之前,網頁開發人員可以打造體驗,讓使用者在 Chrome 中看到的本機內容與遠端螢幕上看到的內容不同,同時仍可在本機控制這項體驗。相關範例包括在電視播放影片時管理 youtube.com 上的播放佇列,或在 Hangouts 工作階段中在全螢幕播放時,用筆記型電腦上查看附有演講者備忘稿的投影片捲盤。

但在某些情況下,使用者可能會只想要在附加的螢幕畫面上呈現內容。舉例來說,假設使用者在會議室中用了透過 HDMI 傳輸線連接的投影機。比起將簡報鏡像投射到遠端端點,使用者確實希望在投影機上以全螢幕播放投影片,讓筆記型電腦的螢幕可供演講者備忘稿和投影片控制使用。雖然網站作者能以非常嚴格的方式支援這項功能 (例如彈出新視窗,使用者必須手動將視窗拖曳至次要螢幕並將畫面放到最大),但本機和遠端呈現作業的效果可能會不一致。

分享網頁

我將說明如何使用 Presentation API,在次要連接的螢幕上呈現網頁。最終結果可在 https://googlechrome.github.io/samples/presentation-api/ 取得。

首先,我們會建立新的 PresentationRequest 物件,並在其中加入您希望在次要連接的螢幕上顯示的網址。

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);
  });

如要顯示簡報顯示提示,您必須要求使用者做出手勢,例如點選按鈕。因此,請在使用者點選按鈕時呼叫 presentationRequest.start(),等待承諾在使用者選取簡報顯示畫面後解決 (例如在本範例中為次要連接的螢幕)。

function onPresentButtonClick() {
  presentationRequest.start()
  .then(connection => {
    console.log('Connected to ' + connection.url + ', id: ' + connection.id);
  })
  .catch(error => {
    console.log(error);
  });
}

如果您連線至網路放送廣告,使用者看到的清單中可能還會包含遠端端點,例如 Chromecast 裝置。請注意,鏡像顯示不在清單中。請參閱 http://crbug.com/840466

簡報顯示挑選器
簡報顯示挑選器

當 promise 解析時,PresentationRequest 物件網址的網頁就會顯示為所選螢幕。哇啊!

我們現在可以進一步監控「關閉」和「終止」事件,如下所示。請注意,您可以使用 presentationRequest.reconnect(presentationId) 重新連線至「已關閉」的 presentationConnection,其中 presentationId 是前一個 presentationRequest 物件的 ID。

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.');
});

與網頁通訊

您覺得這樣很好,但該如何在控制器頁面 (剛剛建立的頁面) 和接收器頁面 (我們傳遞至 PresentationRequest 物件) 之間傳遞訊息。

首先,使用 navigator.presentation.receiver.connectionList 在接收器頁面上擷取現有連線,並監聽傳入的連線,如下所示。

// 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);
  });
}

接收訊息的連線會觸發「訊息」事件,您可以監聽這個事件。 訊息可以是字串、Blob、ArrayBuffer 或 ArrayBufferView。 傳送方式就像從控制器頁面或接收器頁面呼叫 connection.send(message) 一樣。

// Controller page

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

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

歡迎參考 https://googlechrome.github.io/samples/presentation-api/ 的範例,瞭解運作方式。相信你也會像我一樣享受此內容。

範例和示範

可以查看我們在本文中使用的官方 Chrome 範例

我也推薦使用互動式 Photowall 示範。這個網頁應用程式可讓多個控制器共同在簡報螢幕上顯示相片投影片。程式碼可在 https://github.com/GoogleChromeLabs/presentation-api-samples 取得。

Photowall 示範螢幕截圖
相片來源:José Luis Mieza / CC BY-NC-SA 2.0

還有一件事

Chrome 提供「投放」瀏覽器選單,使用者可以在造訪網站時隨時叫用。如要控制這個選單的預設呈現方式,請將 navigator.presentation.defaultRequest 指派給先前建立的自訂 presentationRequest 物件。

// Make this presentation the default one when using the "Cast" browser menu.
navigator.presentation.defaultRequest = presentationRequest;

開發人員提示

如要檢查接收器頁面並進行偵錯,請前往內部 chrome://inspect 頁面,選取「其他」,然後按一下目前顯示網址旁的「檢查」連結。

檢查簡報接收器頁面
檢查簡報接收器頁面

您也可以查看內部 chrome://media-router-internals 頁面,深入瞭解內部探索/可用性程序。

後續步驟

自 Chrome 66 起,支援 ChromeOS、Linux 和 Windows 平台。我們將於日後停止支援 Mac。

資源