萬盛學電腦網

 萬盛學電腦網 >> 網頁制作 >> DivCSS教程 >> 多屏復雜動畫CSS技巧三則

多屏復雜動畫CSS技巧三則

 

    當下CSS3應用已經相當廣泛,其中重要成員之一就是CSS3動畫。並且,隨著CSS動畫的逐漸深入與普及,更復雜與細膩的動畫場景也如雨後春筍般破土而出。

     

    例如上個月做的「企業QQ-新年祝福」活動:

     

    雖然視頻內容是手機上的顯示效果,但是,這個“企業新年祝福活動”原本只針對桌面端,移動端是後來輔助增強(增加了相當於活動頁面UV 5.7%的點擊)。而目前大多數類似頁面只針對移動端,例如其他同事實現的QQ空間5.0預約頁第二版:

    多屏復雜動畫CSS技巧三則 三聯

    掃碼(需登錄)或者鏈接二選一:

    經驗分享:多屏復雜動畫CSS技巧三則

    因此,需要多一點適配的技巧。但是,對於動畫效果實現,其實都是一脈相承的,最終的實現需要很多點滴積累,我這裡講三個部分同學可能不知道的相關CSS技巧。

    注:示例代碼的私有前綴均省略,大家自行腦補

    技巧一、使用animation-play-state控制每屏動畫播放

    1. 類名active與動畫觸發
    首先,使用active觸發每一屏的動畫,幾乎已經約定俗成,應該也建議成為默認的行業規范。

    一般做法是,當對應一屏內容進入的時候,使用JS給容器添加類名active:

    container.classList.add("active");

    如果你做的動畫逼格較高,希望每次浏覽這一屏內容的時候,動畫都走一遍,可以使用reflow重新觸發一下animation:

    container.classList.remove("active");
    container.offsetWidth = container.offsetWidth;
    container.classList.add("active");

    2. 類名active與動畫控制技巧
    如何具體控制動畫的播放呢?我們通常第一反應是使用下面的方法實現,動畫的完整CSS代碼在active狀態下呈現,如:

    .element1 { /* 尺寸與定位 */ }
    .element2 { /* 尺寸與定位 */ }
    .element3 { /* 尺寸與定位 */ }
    ....active .element1 { animate: name1 1s; }
    .active .element2 { animate: name2 1s; }
    .active .element3 { animate: name2 1s; }
    ...

    從實現和功能上將,上面方法是很不錯的,通俗易懂,不易犯錯。不過我個人更喜歡使用配合CSS3的animation-play-state屬性對每屏動畫進行控制,實現如下:

    1. 動畫相關CSS代碼直接寫在元素上:
      .element1 { /* 尺寸與定位 */ animate: name1 1s; }
      .element2 { /* 尺寸與定位 */ animate: name2 1s; }
      .element3 { /* 尺寸與定位 */ animate: name3 1s; }
      ...
    2. 創建一個類名,如.animate,凡是使用到了animation動畫的元素都添加這個類名;
    3. 如下CSS代碼:
      .animate {
      animation-play-state: paused;
      }
      .active .animate {
      animation-play-state: running;
      }

    之所以個人更喜歡後面的方法,是因為有一種“無侵入”的感覺,代碼層次清晰,控制關系明確。有利於後期的維護與擴展。

    然而,使用animation-play-state還是有些需要注意的,對於IE10/IE11浏覽器,animation-play-state是不能簡寫的。如:

    .element { animate: shake 4s 2s both infinite paused; }

    只會讓整個CSS聲明掛掉的!如下寫法支持:

    .element { 
    animate: shake 4s 2s both infinite;
    animation-play-state: paused;
    }

    經驗分享:多屏復雜動畫CSS技巧三則

    首先,我們不能無視主流手機之Windows Phone. 其次,帥氣的翻屏動畫並不是移動端專有,桌面端也適用。稍稍用力,桌面移動全適配,何樂而不為!

    技巧二、不同狀態下的連續動畫

    有時候,動畫可能不是一波流,分狀態。

    例如,我們的小火箭,先是淡出動畫,然後無限上下懸浮。怎麼實現呢?

    經驗分享:多屏復雜動畫CSS技巧三則

    關鍵點就是動畫分解與延時。

    據我所知,沒辦法只使用一個keyframes關鍵幀聲明就實現這個效果,因為,這裡有動畫狀態的變化:一個只執行一次的動畫和一個無限循環動畫。

    怎麼辦?我們可以將動畫分解,寫2個animation keyframes動畫關鍵幀描述。

    @keyframes fadeIn { /* ... */ }
    @keyframes float { /* ... */ }

    然後,再分別應用這些關鍵幀動畫。如何應用呢?有2個小技巧:

    1. 逗號與多animation動畫值
    如下:

    <div class="element">小火箭</div>.element { animation: fadeIn 1s, float .5s 1s infinite; }
      /* 我淡出, 需要1秒;我1秒後開始無限漂浮 */

    其中float .5s 1s infinite這裡的1s就是無限漂浮動畫執行延遲的時間,於是,兩個動畫完美配合,感覺就像是一個動畫。實際上,就是一個動畫,所有CSS3 animation動畫走同一個UI線程,這也是為何推薦使用CSS實現動畫效果的原因。

    此寫法沒有兼容性問題,大家可以開開心心地使用。

    2. 標簽嵌套與獨立動畫
    我們還可以通過嵌套標簽的形式實現連續動畫,例如:

    <div class="element-wrap"><div class="element">小火箭</div></div>.element-wrap { animation: fadeIn 1s; }
              /* 我淡出, 需要1秒 */
    .element { animation: float .5s 1s infinite; } /* 我1秒後開始無限漂浮 */

    有人可能會奇怪了。animation本身就支持多動畫並行,你還搞個標簽嵌套,沒有任何使用的理由啊!沒錯,單純看我們這個例子,確實是這樣。但是:

    ① 提取公用動畫
    這類多屏動畫是有N多元素同時執行不同的動畫。比方說,火箭是淡出,然後上下漂浮;火箭的火焰是淡出,然後大小變化;黑洞是淡出,然後左右隨波。你如何實現?

    如果純粹借助animation語法,應該是:

    .element1 { animation: fadeIn 1s, float .5s 1s infinite; }  /* 我淡出, 需要1秒;我1秒後開始無限漂浮 */
    .element2 { animation: fadeIn 1s, size .5s 1s infinite; } /* 我淡出, 需要1秒;我1秒後開始大小變化 */
    .element3 { animation: fadeIn 1s, move .5s 1s infinite; } /* 我淡出, 需要1秒;我1秒後開始左右移動 */

    可以看到,淡出是公用的動畫效果,我們可以借助嵌套標簽,實現公用語法的合並,方面後期維護:

    .element-wrap { animation: fadeIn 1s; }          /* 大家都1秒淡出 */
    .element1 { animation: float .5s 1s infinite; } /* 我1秒後無限漂浮 */
    .element2 { animation: size .5s 1s infinite; } /* 我1秒後忽大忽小 */
    .element3 { animation: move .5s 1s infinite; } /* 我1秒後左右移動 */

    ②避免變換沖突
    有個元素動畫是邊360度旋轉、邊放大(從0放大到100%),像這種具有典型特征的動畫我們顯然要獨立提取與公用的:

    @keyframes spin { /* transform: rotate... */ }
    @keyframes zoomIn { /* transform: scale... */ }

    好了,現在問題來了,變放大邊旋轉:

    .element { animation: spin 1s, zoomIn 1s; }  /* 旋轉:啊,完蛋啦,我被放大覆蓋啦! */

    由於都是使用transform, 發生了殘忍的覆蓋。當然,有好事的人會說,你使用zoom不就好了!確實,如果只是移動端,使用zoom確實棒棒哒!但是,我們這個企業活動,PC是主戰場,因此,FireFox浏覽器(FF不識zoom)是不能無視的。

    怎麼辦?重新建一個名為spinZoomIn的動畫關鍵幀描述還是?

    經驗分享:多屏復雜動畫CSS技巧三則

    .element-wrap { animation: spin 1s; }   /* 我轉轉轉 */
    .element { animation: zoomIn 1s; } /* 我大大大 */

    技巧三、無侵入定位和居中定位准則

    1. 這裡的“無侵入定位”指不受animation影響的元素定位,包含兩部分:一是不使用keyframes關鍵幀決定初始位置;二是不要使用keyframes中出現的屬性定位。

    ①. 不使用keyframes決定初始位置
    應該都知道,CSS3 animation的fill-mode可以決定元素動畫結束前後的位置,也就是也具有定位的作用。此時,可能就會有小伙伴,故作聰明,利用animation keyframes 0% {}或form {}去做定位,貌似,還省了寫代碼。看上去很贊,實際上狹隘了,這對於對animation支持不佳或不支持的浏覽器實際上是不友好的,例如Android2.3不支持animation-fill-mode, IE6-IE9不支持CSS3 animation,於是乎,當遭遇這些浏覽器的

copyright © 萬盛學電腦網 all rights reserved