查看單頁應用程式的轉換

網頁的常見模式是使用 JavaScript 動態取代網頁上的內容,而不載入新的完整 HTML 文件。這就是所謂的單頁應用程式 (SPA)。檢視畫面轉場效果可讓您在 SPA 的網頁之間顯示連續性或脈絡。

整頁轉場效果

當使用者在 SPA 中前往新檢視畫面時,架構會以新內容取代 DOM。這樣內容就會顯示出來,但如果想在目前內容和新內容之間提供轉場效果,該怎麼做呢?

轉換效果通常會同時顯示舊檢視區塊和新檢視區塊,例如淡出舊檢視區塊,同時淡入新檢視區塊。由於現有內容會遭到取代,因此在檢視畫面轉換功能推出前,這項作業相當困難。

如要使用檢視畫面轉場效果,您必須將變更 DOM 的邏輯包裝在回呼中。在這些範例中,我們使用名為 MyRouter 的網頁元件提供基本路由器實作。啟用檢視畫面轉場效果的方式,取決於您使用的路由器和架構。

document.startViewTransition(() => updateTheDOMSomehow());

這會啟用預設轉換效果,也就是淡出舊檢視畫面,同時淡入新檢視畫面。

這到底是怎麼一回事?當您呼叫 document.startViewTransition() 時,瀏覽器會擷取舊檢視區塊的快照。接著,它會呼叫您傳遞的回呼函式,將 DOM 更新為新檢視區塊 (但尚未顯示)。回呼函式完成後,瀏覽器就會開始轉換至新內容。

// Fallback for browsers that don't support this API:
if (!document.startViewTransition) {
  updateTheDOMSomehow();
  return;
} else {
  // With a View Transition:
  document.startViewTransition(() => updateTheDOMSomehow());
}

自訂轉場效果

如先前範例所示,預設的檢視區塊轉換會淡出舊檢視區塊,同時淡入新檢視區塊。您可以設定由檢視區塊轉場效果產生的虛擬元素樣式,自訂轉場效果,讓轉場效果更符合網站風格。

你可以使用 ::view-transition-old() 指定離開轉場效果,並使用 ::view-transition-new() 指定進入轉場效果。您也可以使用 ::view-transition-group() 同時指定這兩項值。

在本例中,舊檢視區塊會使用 slide-out-to-left 轉場效果淡出,新檢視區塊則會使用 slide-in-from-right 轉場效果淡入。兩者時間長度都是 200 毫秒。

::view-transition-group(root){
  animation-duration: 200ms;
}

::view-transition-old(root) {
  animation-name: slide-out-to-left;
}

::view-transition-new(root) {
  animation-name: slide-in-from-right;
}

根據內容顯示不同轉場效果

您可能希望根據使用者執行的動作,採用不同的轉場效果。舉例來說,如果從首頁點選連結時,新檢視畫面會從右側滑入,您會預期點選連結返回首頁時,首頁檢視畫面會從左側滑入。

您可以使用 :active-view-transition-type() 虛擬類別指定不同動畫。

html:active-view-transition-type(forwards) {
  &::view-transition-old(root) {
    animation-name: slide-out-to-left;
  }

  &::view-transition-new(root) {
    animation-name: slide-in-from-right;
  }
}

接著,您可以在呼叫 document.startViewTransition() 時,選擇要使用的檢視區塊轉場效果類型。

const direction = next === 'home' ? 'backwards' : 'forwards';

document.startViewTransition({
  update: updateTheDOMSomehow,
  types: [direction],
});

轉換特定元素

到目前為止,您只將轉換套用至根元素,以轉換整個檢視區塊。但您也可以使用檢視區塊轉換,為網頁的特定部分製作動畫。

舉例來說,舊版檢視畫面中的內容可能與新版檢視畫面中的內容相符。可以是內容標題或圖片。舊版檢視畫面可能顯示縮圖,新版檢視畫面則顯示影片。

首先,您需要使用 view-transition-name 屬性指定要轉換的元素。如要讓檢視區塊轉換正常運作,在呼叫 document.startViewTransition() 之前,每個 view-transition-name 都必須有一個元素,且在 document.startViewTransition() 中的回呼完成後,每個 view-transition-name 也必須有一個元素。

在這個範例中,音樂播放器會顯示專輯封面、標題和藝人。替代檢視畫面會顯示重新排列的相同內容,並加入歌詞。

在前例中,新舊檢視畫面中各有一個轉換的元素,而且這些元素甚至共用相同的選取器。轉換的元素會顯示在大小和位置之間移動。檢視畫面中未轉換的部分會淡入和淡出。

請看以下更複雜的範例。舉例來說,網誌首頁可能會顯示每篇文章的標題和圖片,而網誌文章的完整頁面檢視畫面也會顯示這些內容。從首頁導覽至特定文章時,您可能會希望標題和圖片轉換至新位置,提供相關背景資訊。

如要為標題執行這項操作,您必須在舊版檢視畫面中,為標題元素提供不重複的 view-transition-name,並與新版檢視畫面中的標題元素共用,且在新版檢視畫面中不重複。這是一項挑戰,因為首頁有多個標題和圖片,您不知道使用者會點選哪一個。

解決方法有兩種。您可以選擇為首頁上的每則貼文新增專屬 view-transition-name,然後在每則完整貼文中比對該名稱。你可以使用貼文 ID 生成這些連結。另一個選項是使用一般 view-transition-name,但請只在使用者點選貼文後,以及呼叫 document.startViewTransition() 前套用。

設計轉場效果

檢視畫面轉場效果是一組工具,可用來引導使用者,並提供額外的品牌或背景提示。您可能會使用多種技術,找出適合網站的轉場效果。

視所需效果而定,您可能也需要調整元素或動畫。在前例中,我們調整了幾種樣式,以取得平滑的轉場效果。

標題具有 width: fit-content 規則,當您轉換不會換行的文字 (或新舊檢視畫面中的換行方式相同) 時,這項規則會很有用。否則,轉場效果可能會在寬度不同的元素之間進行,導致轉場效果不夠平滑。

圖片在舊版和新版檢視畫面中的長寬比也不同。這個範例會修改動畫和 object-fit 屬性,讓轉場效果看起來更流暢。

尊重prefers-reduced-motion

使用者要求減少動態效果的常見原因是,全螢幕動畫 (例如可透過檢視區塊轉換實現的動畫) 可能會導致前庭運動障礙者感到不適。您可以使用 prefers-reduced-motion 媒體查詢停用動畫。您也可以選擇提供更細微的替代動畫,但仍要傳達元素之間的連結方式。

@media (prefers-reduced-motion) {
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) {
    animation: none !important;
  }
}

隨堂測驗

代表 document.startViewTransition() 呼叫前檢視區塊的虛擬元素名稱為何?

::view-transition-previous
答錯了。
::view-transition-prior
答錯了。
::view-transition-old
答對了!
::view-transition-initial
答錯了。

檢視區塊轉場效果的預設動畫為何?

舊畫面淡出,新畫面淡入
答對了!
從左向右滑動
答錯了。
舊畫面淡入/淡出白畫面,淡入新畫面
答錯了。
星形抹除
答錯了。

網頁的預設 view-transition-name 是什麼?

document
答錯了。
shadow-root
答錯了。
root
答對了!
body
答錯了。