高性能的視差動畫

愛也好,恨也好,視差效果已經遍布web之上了。當你用的巧妙的時候,它可以給應用增加深度和隱喻效果。但問題在於實現一個高性能的視差效果是一個很有挑戰的工作。在這篇文章裡,我們將討論如何構造一個高性能的視差效果,當然同樣重要的是還得跨瀏覽器。

摘要

  • 不要使用滾動事件(scroll events)或者背景定位(background-position)來創建視差動畫。
  • 使用CSS 3D 變換來創建一個更準確的視差效果。
  • 對於iOS移動設備的Safari瀏覽器使用position: sticky來確保視差可以生效。

視差的問題分析

在開始之前,我們先來看兩個現有的常見的實現視差的方法,探討為何它們不適合我們要追求的目標。

不好的方案:使用滾動事件

視差的關鍵需求是它應該是滾動耦合的:對於頁面滾動的每一個位置變化,視差元素的位置也應被更新。這看上去很容易,現代瀏覽器的重要機制之一就是它們可以異步處理工作。儘管如此,在大多數瀏覽器中,滾動事件是被作為“盡量好”(best effort)的工作處理的,也就意味著:瀏覽器並不確保每一幀的滾動動畫送達!

這個重要的信息告訴我們為什麼要避免使用Javascript基於滾動事件去移動元素:Javascript並不能確保視差會和頁面滾動保持同樣的步調。。在一些老版本的Mobile Safari上,滾動事件甚至是在滾動完成後才觸發的,這一點讓基於Javascript的滾動效果無法實現。在較新的Mobile Safari版本中,滾動事件可以在動畫過程中觸發了,但是和Chrome一樣,它是一個基於“盡量好”的原則的。所以當主線程忙於其他工作時,滾動事件不會立即觸發,也就意味著視差效果的丟失。

不好的方案:更新背景位置

我們要避免的另一個場景是在每幀都進行繪製。很多方案試圖採用改變background-position來提供視差效果,但這會讓瀏覽器在滾動時重繪受影響的部分,而這可能會是相當消耗資源的,這種影響會使動畫卡頓。

如果我們想提供一個高質量的視差動畫,我們想要的是一個可以當作加速的屬性(這裡我們指的是transform和opacity),而這是不依賴於滾動事件的。

CSS 3D

Scott Kellum和Keith Clark都已經在利用CSS 3D來實現視差效果領域做出了很重要的工作。他們採用的非常有效技術有:

  1. 建立一個容器元素,設置overflow-y: scroll使其可以滾動(同時可能需要overflow-x: hidden)。
  2. 對於上面的元素,我們會應用一個perspective值,然後設置perspective-origin到top left,或者0 0。
  3. 對上面元素的子元素應用一個在Z 軸的變換,然後把它們還原回來以實現視差效果,而沒有影響它們在屏幕上的大小。

(此篇文章為網路轉載,如有冒犯,請來信告知,當即刻移除!)