高效能視差

Paul Lewis
Robert Flack
Robert Flack

無論喜歡還是討厭,癱瘓相關內容將繼續保持。謹慎使用可以 為網頁應用程式增添深度和巧思。但問題在於 但要做到這一點 就很難做到這一點本文將說明 討論一個兼具效能與效能的解決方案,同樣重要的是 具備跨瀏覽器間的連線

視差插圖。

重點摘要

  • 請勿使用捲動事件或 background-position 建立視差動畫。
  • 使用 CSS 3D 變形功能產生更準確的視差效果。
  • 如果是行動版 Safari,請使用 position: sticky 確保視差效果

如需置入式解決方案,請前往 UI Element Samples GitHub 存放區 視差輔助 JS! 您可在 存取 Cloud Bigtable 或 GitHub 存放區

問題視差

首先,我們來看看達成視差效果的兩種常見方式

錯誤:使用捲動事件

視差的主要需求是,應以捲動的方式進行捲動;的 當頁面捲動位置時,每個變更動作都會跟著顯示視差元素 位置應該就會更新。聽起來很簡單,但這是 新式瀏覽器是以非同步方式運作。這適用於 捲動事件大多數瀏覽器捲動事件都會傳送 「盡可能」而且不保證會在每個影格中都放送 捲軸動畫!

這些重要資訊能夠說明為何必須避免 根據捲動事件移動元素的 JavaScript 解決方案: JavaScript 無法保證視差程序會繼續進行 頁面捲動位置時一併顯示。在舊版的行動版 Safari 中,捲動事件是 因此無法在捲動頁面結束時看到 以 JavaScript 為基礎的捲動效果。較新版本「會」傳送捲動事件 與 Chrome 類似,我們仍會「盡力」。如果 主要執行緒忙於處理任何其他工作,則系統不會傳送捲動事件 ,這表示視差效果將會遺失。

錯誤:正在更新 background-position

另一個我們想要避免的情況是在每個畫面繪製。許多解決方案 嘗試變更 background-position,以提供視差樣式, 瀏覽器會在捲動時重新繪製網頁上受影響的部分, 可能耗用足以導致動畫大量資源浪費的成本

如果我們想要實現視差運動的保證,我們會需要 做為加速屬性 (目前也就是 轉換和不透明度),並且不需要捲動事件。

3D 中的 CSS

Scott KellumKeith Clark 都擁有 使用 CSS 3D 來完成視差動作 他們使用的技巧就是:

  • 設定內含 overflow-y: scroll 捲動的包含元素 (可能 overflow-x: hidden)。
  • 對同一個元素套用 perspective 值和 perspective-origin 設為 top left0 0
  • 至該元素的子項,在 Z 中套用翻譯,再將其縮放 以便提供視差動態效果,而不會影響畫面大小。

這種做法的 CSS 外觀如下:

.container {
  width: 100%;
  height: 100%;
  overflow-x: hidden;
  overflow-y: scroll;
  perspective: 1px;
  perspective-origin: 0 0;
}

.parallax-child {
  transform-origin: 0 0;
  transform: translateZ(-2px) scale(3);
}

假設有一個類似下方的 HTML 程式碼片段:

<div class="container">
    <div class="parallax-child"></div>
</div>

調整畫面大小

推回子項元素會使子元素與 讓所有員工都能獲得相同的價值如要計算增加多少費用 這個算式:(perspective -距離) / 透視。我們很有可能 您希望視差元素呈現視差元素 但符合我們編寫的大小 就必須以這種方式擴大規模,而不是維持原狀

就上述程式碼而言,視角為 1px,而 parallax-child 的 Z 距離為 -2 像素。也就是說,該元素 3 倍向上擴充,可以看到加到程式碼中的值: scale(3)

針對未套用 translateZ 值的任何內容,您可以 並將值替換成零。這表示比例尺為 (perspective - 0) / ,淨值為 1,表示已縮放 上下都一樣非常方便。

這個方法的運作方式

重點在於說明效果的賣點,因為我們會用這個功能 知識捲動是一次轉換效果,所以 accelerated;基本上就是藉由在 GPU 移動層在 一般的捲動功能,意指不需任何視角 發生在比較捲動元素及其子項時 1:1 的方式 如果向下捲動元素 300px,其子項就會進行轉換 相同金額:300px

但是,為捲動元素套用透視值會分散在周圍 指令會變更支撐捲動轉換指令的矩陣 現在捲動 300 像素時,子項只能移動 150 像素, 您選擇的 perspectivetranslateZ 值。如果元素 translateZ 的值為 0,此時會 (如前所述) 捲動為 1:1,但子項會設為子項 而在 Z 語言推進來的去法來源,則會在 率!淨結果:視差動態。而且最重要的是 部分瀏覽器內部的捲軸式機器會自動載入 無需監聽 scroll 事件或變更 background-position

勇於創新之旅:Mobile Safari

每個效果都設有註意事項,轉換效果很重要 會保留 3D 效果到子項元素如果 階層與視差子項之間的階層關係 3D 視角呈現「扁平化」的景象,表示效果已經遺失。

<div class="container">
    <div class="parallax-container">
    <div class="parallax-child"></div>
    </div>
</div>

在上述 HTML 中,.parallax-container 是新的,可有效 壓平 perspective 值,我們會失去視差效果。解決方案 在大多數情況下,做法都相當簡單明瞭:您可以在前面加上 transform-style: preserve-3d ,讓該元素傳播任何 3D 效果 (如我們的視角) 您在樹狀結構中進一步套用的數值。

.parallax-container {
  transform-style: preserve-3d;
}

但以行動版 Safari 來說,事情會有些許差異。 技術上來說,將 overflow-y: scroll 套用至容器元素可正常運作,但 繪製捲動元素所需的成本解決方法是 -webkit-overflow-scrolling: touch,但也會壓平 perspective 我們不可能遇到任何視差問題

從循序漸進的觀點來看,我們認為 問題。如果我們無法在所有情況下都無法採用視差廣告,應用程式仍可正常運作,但 很樂意找出解決方法

position: sticky就能解決問題!

事實上,有些幫助是 position: sticky 形式, 允許元素「固定」或特定父項元素的頂端 頁面標題規格本身和其中大多數規定相同,但包含 實用的小寶石:

乍看之下,這可能不算划算,只是 也就是元素的黏著度 計算:"偏移值是以參照最接近的上階進行計算 有捲動方塊」換句話說, (為了讓圖片能附加至其他元素或可視區域), 計算時是在套用任何其他轉換「之前」計算而來,而非「之後」。也就是說 與前述的捲動範例非常相似,如果計算偏移值 300px 的進步空間,讓我們有機會運用觀點 (或任何其他轉場效果) 先操控 300 像素的偏移值,再將值套用至任何固定式 元素。

position: -webkit-sticky 套用至視差元素後 有效地「反向」會造成 -webkit-overflow-scrolling: touch 的平緩效果這可確保視差元素參照距離最近的 含有捲動方塊的祖系,在本例中為 .container。接著: 和先前一樣,.parallax-container 會套用 perspective 值。 這會變更計算出的捲動位移並創造視差效果。

<div class="container">
    <div class="parallax-container">
    <div class="parallax-child"></div>
    </div>
</div>
.container {
  overflow-y: scroll;
  -webkit-overflow-scrolling: touch;
}

.parallax-container {
  perspective: 1px;
}

.parallax-child {
  position: -webkit-sticky;
  top: 0px;
  transform: translate(-2px) scale(3);
}

這會還原行動版 Safari 的視差效果,這是個好消息 回合!

固定位置注意事項

但這裡「確實」不同,但 position: sticky「會」變更 視差技術。固定位置會嘗試將元素與 而非固定式版本則沒有也就是說, 使用固定式視差效果會變成相反內容,但沒有:

  • 使用 position: sticky 時,較接近的元素為 z=0 較少 移動。
  • 如果不使用 position: sticky,則較靠近元素為 z=0 就會移動。

如果覺得這些概念還不夠抽象,請觀看這部由 Robert Flack 提供的示範影片, 示範元素在採用和未固定格的情況下,各元素的行為有何差異 位置。您必須使用 Chrome Canary (第 56 版),才能查看兩者的差異 Safari) 或 Safari。

視差透視螢幕截圖

Robert Flack 示範 position: sticky 會影響視差捲動。

各種錯誤和解決方法

就像其他事情一樣 還是有些時候還有懸浮微粒和凹槽 平滑化:

  • 固定式支援不一致。仍在使用 Chrome、Edge 並未完全支援,而 Firefox 則在固定式與透視轉換的結合時出現繪製錯誤。因此 建議您添加一小段程式碼,只加入 position: sticky ( -webkit- 前置字元),也就是行動版 Safari 。
  • 影響力不只「有效」在 Edge 中。Edge 會嘗試處理 OS 層級,這通常是個好現象,但本例可避免 偵測捲動期間的視角變化如要修正這個問題,請將 固定的位置元素,因為這似乎將 Edge 切換到 非 OS 捲動方法。 並確保將觀點納入考量
  • 「網頁上的內容數量龐大!」許多瀏覽器考量到 決定網頁的內容大小時 可惜的是 Chrome 和 Safari 保持觀點清楚明確以下內容 如果有 3 倍比例套用至元素 即使元素大小在 已套用「perspective」。如要解決這個問題, 從右下角 (使用 transform-origin: bottom right) 縮放元素的縮放比例,這種做法會導致過大的元素擴大進入 「排除區域」(通常是左上角) 的可捲動區域;可捲動 您永遠都無法看到或捲動排除排除區域的內容。

結論

請謹慎使用視差效果,是有趣的效果。如您所見 以高效能、捲動耦合和跨瀏覽器的方式實作。 因為這需要多點數學運算 為了達到所需效果 我們封裝了一個小型輔助程式庫 您可以在 UI 元素範例 GitHub 存放區中找到這個範例。

現在就開始試用吧!