捲動及縮放已擷取的分頁

François Beaufort
François Beaufort

網頁平台已可透過 Screen Capture API 分享分頁、視窗和畫面。當網頁應用程式呼叫 getDisplayMedia() 時,Chrome 會提示使用者以 MediaStreamTrack 影片的形式,與網頁應用程式分享分頁、視窗或畫面。

許多使用 getDisplayMedia() 的網路應用程式會向使用者顯示擷取畫面的影片預覽畫面。舉例來說,視訊會議應用程式通常會將這部影片串流傳輸給遠端使用者,同時也會將影片算繪至本機 HTMLVideoElement,讓本機使用者持續看到自己分享內容的預覽畫面。

本文將介紹 Chrome 中的新版 Captured Surface Control API,讓網頁應用程式捲動擷取的索引標籤,以及讀取和寫入擷取索引標籤的縮放層級。

使用者捲動及縮放擷取的索引標籤 (示範)。

為什麼要使用擷取的 Surface 控制項?

所有視訊會議應用程式都有同樣的缺點。如果使用者想與擷取的索引標籤或視窗互動,就必須切換到該介面,離開視訊會議應用程式。這會造成一些問題:

  • 除非使用者使用子母畫面,或為視訊會議分頁和共用分頁開啟並排視窗,否則無法同時查看擷取的應用程式和遠端使用者的視訊串流。在較小的螢幕上,這可能會很困難。
  • 使用者必須在視訊會議應用程式和擷取的畫面之間切換,造成負擔。
  • 使用者離開視訊會議應用程式後,就無法存取該應用程式提供的控制項,例如嵌入式即時通訊應用程式、表情符號回應、要求加入通話的使用者通知、多媒體和版面配置控制項,以及其他實用的視訊會議功能。
  • 簡報者無法將控制權委派給遠端參與者。這會導致遠端使用者要求簡報者變更投影片、稍微上下捲動,或調整縮放比例等常見情況。

Captured Surface Control API 可解決這些問題。

如何使用擷取的表面控制項?

如要順利使用「擷取的表面控制項」,需要完成幾個步驟,例如明確擷取瀏覽器分頁,並取得使用者授權,才能捲動及縮放擷取的分頁。

擷取瀏覽器分頁

首先,請提示使用者使用 getDisplayMedia() 選擇要分享的介面,並在過程中將 CaptureController 物件與擷取工作階段建立關聯。我們很快就會使用該物件來控制擷取的表面。

const controller = new CaptureController();
const stream = await navigator.mediaDevices.getDisplayMedia({ controller });

接著,以 <video> 元素的形式,產生擷取表面的本機預覽畫面:

const previewTile = document.querySelector('video');
previewTile.srcObject = stream;

如果使用者選擇分享視窗或畫面,目前不在範圍內,但如果選擇分享分頁,我們可能會繼續進行。

const [track] = stream.getVideoTracks();

if (track.getSettings().displaySurface !== 'browser') {
  // Bail out early if the user didn't pick a tab.
  return;
}

權限提示

在特定 CaptureController 物件上首次叫用 forwardWheel()increaseZoomLevel()decreaseZoomLevel()resetZoomLevel() 時,系統會顯示權限提示。如果使用者授予權限,後續即可呼叫這些方法。

必須有使用者手勢才能向使用者顯示權限提示,因此應用程式應僅在已具備權限,或回應使用者手勢 (例如在網頁應用程式中點選相關按鈕) 時,才呼叫上述方法。click

捲動

使用 forwardWheel(),擷取應用程式可將擷取應用程式本身來源元素中的滾輪事件,轉送至擷取索引標籤的可視區域。對擷取的應用程式而言,這些事件與使用者直接互動並無區別。

假設擷取應用程式採用名為 "previewTile"<video> 元素,下列程式碼會說明如何將傳送滾輪事件轉送至擷取的索引標籤:

const previewTile = document.querySelector('video');
try {
  // Relay the user's action to the captured tab.
  await controller.forwardWheel(previewTile);
} catch (error) {
  // Inspect the error.
  // ...
}

方法 forwardWheel() 會採用單一輸入,可以是下列任一項目:

  • HTML 元素,系統會將滑鼠滾輪事件從這個元素轉送至擷取的索引標籤。
  • null,表示應停止轉送。

成功呼叫 forwardWheel() 會覆寫先前的呼叫。

在下列情況下,forwardWheel() 傳回的 Promise 可能會遭到拒絕:

  • 如果擷取工作階段尚未開始或已停止。
  • 使用者未授予相關權限。

縮放

如要與擷取的分頁縮放比例互動,請使用下列 CaptureController API 介面:

getSupportedZoomLevels()

這個方法會傳回瀏覽器支援的縮放層級清單,適用於擷取的表面類型。這份清單中的值會以百分比表示,相對於「預設縮放等級」(定義為 100%)。清單會單調遞增,且包含值 100。

這個方法只能針對支援的顯示介面類型呼叫,目前僅適用於分頁。

如果符合下列條件,系統可能會呼叫 controller.getSupportedZoomLevels()

  • controller與進行中的擷取作業相關聯。
  • 擷取的是分頁。

否則會引發錯誤。

呼叫這個方法需要 "captured-surface-control" 權限。

zoomLevel

這項唯讀屬性會保留所擷取分頁的目前縮放等級。這是可為空值的屬性,如果擷取的表面類型沒有縮放層級的實用定義,則會保留 null。目前縮放比例僅適用於分頁,不適用於視窗或螢幕。

擷取結束後,屬性會保留最後的縮放等級值。

讀取這項屬性需要 "captured-surface-control" 權限。

onzoomlevelchange

這個事件處理常式可協助監聽所擷取分頁的縮放比例變更。這些情況包括:

  • 使用者與瀏覽器互動,手動變更所擷取分頁的縮放層級。
  • 回應擷取應用程式對縮放設定方法 (如下所述) 的呼叫。

讀取這項屬性需要 "captured-surface-control" 權限。

increaseZoomLevel()」、「decreaseZoomLevel()」和「resetZoomLevel()

這些方法可讓您操控擷取的分頁縮放等級。

increaseZoomLevel()decreaseZoomLevel() 會分別將縮放等級變更為下一個或上一個縮放等級,順序則由 getSupportedZoomLevels() 傳回。resetZoomLevel() 會將值設為 100。

呼叫這些方法時,必須具備 "captured-surface-control" 權限。如果擷取應用程式沒有這項權限,系統會提示使用者授予或拒絕權限。

這些方法都會傳回 Promise,如果呼叫成功,Promise 就會解析,否則就會遭到拒絕。遭到拒絕的可能原因包括:

  • 權限不足。
  • 在擷取開始前呼叫。
  • 在擷取結束後呼叫。
  • 在與擷取畫面相關聯的 controller 上呼叫,但擷取畫面不支援顯示表面類型。(也就是除了擷取分頁以外的任何內容)。
  • 嘗試分別增加或減少超過最大值或最小值。

請注意,建議您避免在 controller.zoomLevel == controller.getSupportedZoomLevels().at(0) 時呼叫 decreaseZoomLevel(),並以類似 .at(-1) 的方式保護對 increaseZoomLevel() 的呼叫。

以下範例說明如何讓使用者直接從擷取應用程式提高所擷取分頁的縮放比例:

const zoomIncreaseButton = document.getElementById('zoomInButton');
zoomIncreaseButton.addEventListener('click', async (event) => {
  if (controller.zoomLevel >= controller.getSupportedZoomLevels().at(-1)) {
    return;
  }
  try {
    await controller.increaseZoomLevel();
  } catch (error) {
    // Inspect the error.
    // ...
  }
});

以下範例說明如何對擷取的索引標籤縮放等級變化做出反應:

controller.addEventListener('zoomlevelchange', (event) => {
  const zoomLevelLabel = document.querySelector('#zoomLevelLabel');
  zoomLevelLabel.textContent = `${controller.zoomLevel}%`;
});

特徵偵測

如要檢查是否支援 Captured Surface Control API,請使用:

if (!!window.CaptureController?.prototype.forwardWheel) {
  // CaptureController forwardWheel() is supported.
}

您也可以使用任何其他 Captured Surface Control API 介面,例如 increaseZoomLeveldecreaseZoomLevel,甚至檢查所有介面。

瀏覽器支援

擷取的 Surface Control 僅適用於電腦版 Chrome 136 以上版本。

安全性和隱私權

"captured-surface-control" 權限政策可讓您管理擷取應用程式和嵌入的第三方 iframe 如何存取擷取的 Surface 控制項。如要瞭解安全性方面的取捨,請參閱「Captured Surface Control」說明文件的「隱私權和安全性注意事項」一節。

示範

您可以執行示範,試用「擷取的 Surface 控制項」。

意見回饋

Chrome 團隊和網路標準社群很想瞭解您使用 Captured Surface Control 的體驗。

請說明設計內容

您是否發現「擷取的表面」擷取功能無法正常運作?或者缺少實作構想所需的方法或屬性?對安全模型有任何疑問或意見嗎?在 GitHub 存放區中提出規格問題,或在現有問題中新增想法。

導入時發生問題嗎?

您是否發現 Chrome 實作方式有錯誤?或者實作方式與規格不同?前往 https://new.crbug.com 回報錯誤。請務必盡可能提供詳細資訊,以及重現問題的步驟。