當前位置:
首頁 > 科技 > 構建高性能展開&收縮動畫

構建高性能展開&收縮動畫

前言

新起點。今日早讀文章由@杜夢傑翻譯授權分享。

正文從這開始~

TL;DR

進行動畫操作時使用scale變換(即transform: scale)。通過限制縮放來阻止子元素在動畫過程中變形。

我們之前已經發布過高性能視差滾動和無限滾動效果的文章。本文將討論如何創建高性能的裁剪動畫(Github repo)。

以展開菜單為例:

GIF/34K

某些製作展開菜單的方法比其他方法更加高性能。

Bad: 動畫操作容器元素的寬高

你可以想到用CSS來操作容器元素的寬度width和高度height。

.menu{

overflow:hidden;

width:350px;

height:600px;

transition:width 600ms ease-out,height 600ms ease-out;

}

.menu--collapsed{

width:200px;

height:60px;

}

這種方法的問題是要求動畫操作寬度width和高度height。這些屬性要求每幀都要計算布局並繪製結果,這是非常耗費性能的並且通常會使幀率低於60fps。如果你不了解這些知識,可以閱讀我們的渲染性能Rendering Performance指導,以便更好的了解渲染過程。

Bad: 使用 CSS clip 或 clip-path 屬性

一種替代方法是使用clip屬性(不贊成使用)來實現展開和摺疊效果。如果你喜歡的話也可以使用clip-path。但是clip-path的支持性比clip差。但是不建議使用clip屬性。是很糾結,但是不要失望,這並不是你想要的解決方法。

.menu{

position:absolute;

clip:rect(0px 112px 175px 0px);

transition:clip 600ms ease-out;

}

.menu--collapsed{

clip:rect(0px 70px 34px 0px);

}

儘管這種方法比操作寬度width和高度height更好,但是缺點是仍舊會觸發重繪。同時,如果你使用clip屬性,要求元素必須是絕對定位absolute或固定定位fixed,這也會造成一些額外的問題。

Good: 動畫縮放

由於這個效果涉及到元素的縮放,你可以使用scale變換。改變transform並不要求改變布局或重新繪製,這是極好的,並且瀏覽器可以把這些改變交給GPU來處理,這就意味著變換效果會被加速並很有可能達到60fps。

這種方法的缺點嘛,就和渲染性能Rendering Performance的很多東西一樣,需要一些準備工作。但絕對是值得的!

Step 1: 計算出初始狀態和結束狀態

使用這種縮放動畫的方法,第一步就是要知道元素展開和收縮時的尺寸。有些情況下你不能一次就得到所有信息,此時你需要切換不同的類來獲取元素的不同狀態。如果你這樣做的話,需要注意一點:如果與上次運行相比,樣式style發生了改變,getBoundingClientRect()(或offsetWidth和offsetHeight)會強制瀏覽器更新樣式和布局styles and layout。

functioncalculateCollapsedScale(){

// The menu title can act as the marker for the collapsed state.

constcollapsed=menuTitle.getBoundingClientRect();

// Whereas the menu as a whole (title plus items) can act as

// a proxy for the expanded state.

constexpanded=menu.getBoundingClientRect();

return{

x:collapsed.width/expanded.width,

y:collapsed.height/expanded.height

}

}

如果操作目標是菜單這樣的對象,我們可以合理假設它的初始狀態就是自然比例(1,1)。這個自然比例代表展開狀態,這意味著需要從縮小的狀態(上面計算出來的)回到自然比例。

但是,這種方法也會縮放菜單的內容。如下圖所示:

GIF/150K

我們應該怎麼做呢?你可以為內容應用counter-transform,例如容器縮小到原始尺寸的1/5,你可以把內容放大5倍來避免內容被擠壓。

有兩點需要注意:

counter-transform也是一種縮放操作。就像容器上的動畫一樣,它也可以被加速。需要確保動畫操作的元素有自己的compositor layer,為了這一點可以為元素添加will-change: transform,如果你需要支持舊版瀏覽器,添加backface-visibility: hiddden。

counter-transform每一幀都必須計算。這裡就有點棘手了,假設動畫是在CSS中且使用了緩動函數easing function,在進行counter-transform操作時緩動函數本身也需要抵消。但是,計算出反曲線,例如cubic-bezier(0, 0, 0.3, 1),並不是那麼簡單。

使用JavaScript來實現這個動畫效果確實很誘人。畢竟,這樣的話你就可以使用一個緩動方程來計算出每一幀縮放和反縮放scale and counter-scale的值。當主線程忙碌時就會體現出所有基於JavaScript的動畫的缺點,你的動畫會阻塞在一起,這對用戶體驗很不好。

Step 2: 動態創建CSS動畫

解決方法看起來可能有些奇怪,就是使用緩動函數動態的創建關鍵幀動畫keyframed animation並注入到頁面中讓菜單使用。這種方法的主要好處是關鍵幀動畫實現的變形可以運行在compositor上,不會被主線程上的任務所干擾。

為了製作關鍵幀動畫,我們計算出從0%到100%之間元素及其內容所需要的縮放值。這些關鍵幀動畫可以壓縮為一個字元串作為一個style element注入到頁面中。注入樣式會導致頁面重新計算樣式Recalculate Styles,這個額外工作是瀏覽器必須做的,但只會在組件啟動時運行一次。

functioncreateKeyframeAnimation(){

// Figure out the size of the element when collapsed.

let{x,y}=calculateCollapsedScale();

letanimation= ;

letinverseAnimation= ;

for(letstep=;step

// Remap the step value to an eased one.

leteasedStep=ease(step/100);

// Calculate the scale of the element.

constxScale=x+(1-x)*easedStep;

constyScale=y+(1-y)*easedStep;

animation+=`${step}% {

transform: scale(${xScale},${yScale});

}`;

// And now the inverse for the contents.

constinvXScale=1/xScale;

constinvYScale=1/yScale;

inverseAnimation+=`${step}% {

transform: scale(${invXScale},${invYScale});

}`;

}

return`

@keyframes menuAnimation {

${animation}

}

@keyframes menuContentsAnimation {

${inverseAnimation}

}`;

}

你可能會對for循環里的ease()函數非常好奇。你可以使用類似這樣的函數來使從0到1的值轉化為對應的過渡值。

functionease(v,pow=4){

return1-Math.pow(1-v,pow);

}

點擊展開全文

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 前端早讀課 的精彩文章:

BATJ 前端面試的 5 大關鍵點,你 Get 到了嗎?
坦然面對:應對前端疲勞
JSON schema與表單驗證
4種使用webpack提升vue應用的方式

TAG:前端早讀課 |

您可能感興趣

高性能電磁波屏蔽材料研究取得新進展
潛心研究更高性能動力電池
輕奢高性能輕薄本已成為市場主力 英特爾創新技術推動形態變革
高性能銅網格柔性透明電極研究取得新進展
高性能、高可用平台架構的演變過程
距離柔性電視與高性能的可穿戴智能設備更進一步
高性能導熱複合材料研究獲系列進展
高性能纖維材料,構建現代科技的骨架
移動固態硬碟好用處:改造高性能電腦
AI驅動的山石網科 用高性能與高智能不斷實現安全進化
單伺服器高性能模式
科研人員開發出高性能鎂電池用凝膠聚合物電解質
運用實時可視化與高性能渲染技術打造高品質影視內容
IMEC使用3D列印技術研發出聚合物噴洒式晶元冷卻器,性能和體積均大幅優於傳統方法,為高性能晶元提供更多散熱方案
研究人員成功製備仿蜘蛛絲結構的高性能導電水凝膠纖維
大眾用量子計算開發下一代高性能電動汽車電池
全球高性能計算髮展態勢分析
我國高性能纖維行業的發展現狀及展望簡介
電極「牽手」電解液協同增強實現高性能超級電容器
可用於製作高性能新型探測器的人造光學材料