今天寫一個css動畫時遇到一個有意思的問題,記錄如下:
1.需求:
等待元素A的動畫加載完,再加載B元素的動畫(下圖中A為大熊貓,B為下方卡片)
先來看下最后的效果啦:
2.初始思路:
在B元素的動畫屬性上加上delay(延遲,使得這個延遲時間 = A元素動畫的加載時間)
即:animation : bmove .7s .7s 1; (這里的第二個.7s即delay時間0.7秒)
b的動畫過程代碼如下:
@keyframes bmove {
0% { margin-top: 100%; opacity: 0 }
100% { margin-top: 0%;opacity: 1 }
}
出現bug:
可以明顯看出B元素在A做動畫時就已經出現,這顯然是不符合需求的;而其原因就是在B元素delay的過程中一直會處在畫面中,而不是在畫面外等着入場,從這里我們也更能理解animation的暗藏含義:即動畫前和動畫后沒有變化。(這就像你把脈動裝進了可樂的瓶子里,脈動依舊還是脈動,而不是因此就變可樂了),那怎么樣才能使B元素在A做動畫時不要顯示出來呢?怎么樣才能使其乖乖地先呆在畫面之外呢?
很自然地,想到了將其opacity設為0,不過單單這樣,動畫之后它又要消失了,效果見下圖:
再一次證明了animation的暗藏含義:即動畫前和動畫后沒有變化
這個時候自然地想到在動畫后再利用javascript將其opacity設為1,那這樣是不是就能高枕無憂了呢?先試試看
3.JS方法:
先把B的opacity設為0,然后待delay結束,用JS把B的opacity設為1 (用定時器實現,即setTimeout)
實現之后,在電腦上一切ok;然而在手機上運行時,出現了動畫結束之后,B元素又閃了一下再出現的狀況(由於手機不方便錄制gif,所以這里就沒放圖了,大家自行腦補,哈哈)
狀況原因猜想:
手機瀏覽器的js引擎相對css有延遲,導致動畫結束后,setTimeout方法內的回調才執行,使得出現上述狀況
既然這樣,那就徹底放棄把JS融入動畫控制中,因為不同瀏覽器js引擎差異
那怎么樣能使opacity 一開始為0 一段時間之后變為1 呢?
4.優雅的delay方法:
成也delay,敗也delay。如果這時候還繞在使用animation-delay屬性上,那始終沒有辦法,所以干脆跳出delay怪圈,不使用delay!!!
那不使用delay如何辦到delay的效果呢?
答案就是在animation的動畫過程代碼中自己加一段delay動畫過程,話不多說,上代碼:
@keyframes bmove {
0% { margin-top: 100%; opacity: 0 }
100% { margin-top: 0%;opacity: 1 }
}
紅色部分代碼即是手動delay代碼,這時,既可以讓B元素在delay期間不執行動畫,又能讓其初始狀態和結束狀態達到需求,這個時候我們的需求就完美實現啦: