針對傳送門進行實作:順暢瀏覽網頁

瞭解建議的 Portal API 如何改善您的導覽使用者體驗。

宇宙悠久 (Yusuke Utsunomiya)
Yusuke Utsunomiya

確保網頁能快速載入,是提供良好使用者體驗的關鍵。 不過,我們經常忽略的問題是頁面轉換,也就是使用者在切換頁面時看到的內容。

名為 Portals 的全新網路平台 API 提案,旨在簡化使用者「跨越網站」瀏覽過程的體驗。

查看入口網站的實際運作情形:

透過 Portal 順暢嵌入及導航。由 Adam Argyle 建立。

入口網站啟用的功能

單頁應用程式 (SPA) 可以提供不錯的轉場效果,但建構的複雜度較高。多頁面應用程式 (MPA) 較容易建構,但會在多個頁面之間呈現空白畫面。

傳送門可提供上述兩種環境的最佳體驗,也就是 MPA 的複雜性,以及順暢的 SPA 轉換過程。它們可以想成可以嵌入內容的 <iframe>,但與 <iframe> 不同,它們還提供可導覽至其內容的功能。

相信您的心聲: 請先查看我們在 2018 年 Chrome 開發人員高峰會上展示的簡報:

使用傳統版導覽時,使用者必須等候空白畫面,直到瀏覽器完成目的地轉譯為止。透過入口網站,使用者可以體驗動畫,同時 <portal> 會預先轉譯內容,提供順暢的導覽體驗。

在傳送門之前,我們可以使用 <iframe> 將另一個網頁轉譯為其他網頁。我們也加入了動畫,讓使用者可以隨意移動頁面上的頁框。但 <iframe> 無法讓您瀏覽其中內容。傳送門能接近這個差距,實現有趣的用途。

體驗 Portal

透過 about://flags 啟用

翻轉實驗性旗標,試用 Chrome 85 以上版本中的入口網站:

  • 為相同來源導覽啟用 about://flags/#enable-portals 標記。
  • 如要測試跨來源導覽,請一併啟用 about://flags/#enable-portals-cross-origin 標記。

在入口網站實驗的早期階段,我們也建議您設定 --user-data-dir 指令列標記,以便使用完全獨立的使用者資料目錄進行測試。啟用入口網站後,請在開發人員工具中確認你擁有新的 HTMLPortalElement

開發人員工具控制台的螢幕截圖,顯示 HTMLPortalElement

實作入口網站

讓我們來舉個基本導入範例來說明。

// Create a portal with the wikipedia page, and embed it
// (like an iframe). You can also use the <portal> tag instead.
portal = document.createElement('portal');
portal.src = 'https://en.wikipedia.org/wiki/World_Wide_Web';
portal.style = '...';
document.body.appendChild(portal);

// When the user touches the preview (embedded portal):
// do fancy animation, e.g. expand …
// and finish by doing the actual transition.
// For the sake of simplicity, this snippet will navigate
// on the `onload` event of the Portals element.
portal.addEventListener('load', (evt) => {
   portal.activate();
});

就是這麼簡單。在開發人員工具控制台中試用這個程式碼,維基百科頁面應該會開啟。

預覽入口網站樣式示範的 GIF 圖片

如果您想建構在 Chrome 開發人員高峰會上展示的類似產品,做法和上方示範一樣,建議您參考下列程式碼片段。

// Adding some styles with transitions
const style = document.createElement('style');
style.innerHTML = `
  portal {
    position:fixed;
    width: 100%;
    height: 100%;
    opacity: 0;
    box-shadow: 0 0 20px 10px #999;
    transform: scale(0.4);
    transform-origin: bottom left;
    bottom: 20px;
    left: 20px;
    animation-name: fade-in;
    animation-duration: 1s;
    animation-delay: 2s;
    animation-fill-mode: forwards;
  }
  .portal-transition {
    transition: transform 0.4s;
  }
  @media (prefers-reduced-motion: reduce) {
    .portal-transition {
      transition: transform 0.001s;
    }
  }
  .portal-reveal {
    transform: scale(1.0) translateX(-20px) translateY(20px);
  }
  @keyframes fade-in {
    0%   { opacity: 0; }
    100% { opacity: 1; }
  }
`;
const portal = document.createElement('portal');
// Let's navigate into the WICG Portals spec page
portal.src = 'https://wicg.github.io/portals/';
// Add a class that defines the transition. Consider using
// `prefers-reduced-motion` media query to control the animation.
// https://developers.google.com/web/updates/2019/03/prefers-reduced-motion
portal.classList.add('portal-transition');
portal.addEventListener('click', (evt) => {
  // Animate the portal once user interacts
  portal.classList.add('portal-reveal');
});
portal.addEventListener('transitionend', (evt) => {
  if (evt.propertyName == 'transform') {
    // Activate the portal once the transition has completed
    portal.activate();
  }
});
document.body.append(style, portal);

您也能輕鬆執行功能偵測,使用傳送門逐步提升網站效能。

if ('HTMLPortalElement' in window) {
  // If this is a platform that have Portals...
  const portal = document.createElement('portal');
  ...
}

如果您想快速體驗 Portal 的感受,請嘗試使用 uskay-portals-demo.glitch.me。 因此請務必使用 Chrome 85 以上版本存取 Chrome 瀏覽器,並開啟實驗功能旗標

  1. 輸入要預覽的網址。
  2. 系統就會以 <portal> 元素的形式嵌入該網頁。
  3. 按一下預覽畫面。
  4. 動畫播放後即會啟用。

呈現使用入口網站使用故障示範的 GIF

查看規格

我們目前正積極在 Web Incubation Community Group (WICG) 中討論入口網站規格。如要快速掌握相關知識,請參閱一些主要情境。以下說明三項重要功能:

  • <portal> 元素:HTML 元素本身。API 非常簡單。這個屬性包含 src 屬性、activate 函式,以及訊息介面 (postMessage)。activate 會在啟用時採用選用引數將資料傳遞至 <portal>
  • portalHost 介面:portalHost 物件新增至 window 物件。這個步驟可讓您檢查網頁是否以 <portal> 元素的形式嵌入。其也提供與主機互傳訊息 (postMessage) 的介面。
  • PortActivateEvent 介面:<portal> 啟用時觸發的事件。有一個名為 adoptPredecessor 的精簡函式,可用來擷取先前網頁做為 <portal> 元素。這可以讓您在兩個頁面之間建立順暢的導覽和組合體驗。

現在讓我們進一步瞭解基本使用模式。以下清單僅列舉部分例子,說明您可以透過入口網站達成哪些目標,並參考程式碼範例。

自訂以 <portal> 元素嵌入時的樣式

// Detect whether this page is hosted in a portal
if (window.portalHost) {
  // Customize the UI when being embedded as a portal
}

<portal> 元素與 portalHost 之間的訊息

// Send message to the portal element
const portal = document.querySelector('portal');
portal.postMessage({someKey: someValue}, ORIGIN);

// Receive message via window.portalHost
window.portalHost.addEventListener('message', (evt) => {
  const data = evt.data.someKey;
  // handle the event
});

啟用 <portal> 元素並接收 portalactivate 事件

// You can optionally add data to the argument of the activate function
portal.activate({data: {somekey: 'somevalue'}});

// The portal content will receive the portalactivate event
// when the activate happens
window.addEventListener('portalactivate', (evt) => {
  // Data available as evt.data
  const data = evt.data;
});

擷取前身

// Listen to the portalactivate event
window.addEventListener('portalactivate', (evt) => {
  // ... and creatively use the predecessor
  const portal = evt.adoptPredecessor();
  document.querySelector('someElm').appendChild(portal);
});

瞭解自家網頁已成為前身

// The activate function returns a Promise.
// When the promise resolves, it means that the portal has been activated.
// If this document was adopted by it, then window.portalHost will exist.
portal.activate().then(() => {
  // Check if this document was adopted into a portal element.
  if (window.portalHost) {
    // You can start communicating with the portal element
    // i.e. listen to messages
    window.portalHost.addEventListener('message', (evt) => {
      // handle the event
    });
  }
});

只要結合入口網站支援的所有功能,您就能建構出非常精緻的使用者體驗。例如,以下示範展示入口網站如何在網站與第三方嵌入內容之間提供順暢的使用者體驗。

用途和方案

希望您喜歡這份簡短的入口網站導覽!我們迫不及待想看到您的精彩作品!舉例來說,您可以開始使用入口網站來進行非簡單的導覽,例如從產品類別清單頁面預先轉譯暢銷商品的網頁。

另一個重要提醒是,Portal 可用於跨來源導覽,就像 <iframe> 一樣。因此,如果您有多個網站可相互參照,您也可以使用入口網站建立兩個不同網站之間的順暢導覽功能。這種跨來源的使用案例對 Portal 而言相當特殊,甚至可以改善 SPA 的使用者體驗。

歡迎踴躍提供意見

Portal 已可在 Chrome 85 以上版本中進行實驗。社群成員的意見回饋是新版 API 設計的重要一環,歡迎試用,並與我們分享你的想法!如果你有任何功能要求或意見,請前往 WICG GitHub 存放區