CSS動畫小知識

接着前文看《CSS權威指南》,本文整理一些CSS動畫的知識點,同時給出一些例子。css

預備知識

變形 Transform

在CSS動畫中咱們常常須要經過變形來達到一些奇妙的效果。使用 transform 首先要明確變形是基於笛卡爾座標系,也就是一般所說的 x/y/z html

座標系

  • transform 是基於物體自身的座標系,百分比也是基於自身的大小
  • 移動和旋轉的先後順序很重要,由於物體旋轉以後的座標系也跟着旋轉
  • 經常使用函數(live demo):
    • 平移函數:translateXtranslateYtranslateZtranslatetranslate3d
    • 縮放函數:scaleXscaleYscaleZscalescale3d( number, number, number )
    • 旋轉函數:rotateXrotateYrotateZrotaterotate3d( number, number, number, angle)
    • 傾斜函數:skewXskewYskew
    • 視域:perspective( length )
  • 重要屬性:transform-origintransform-stylebackface-visibility
See the Pen FlipCard on CodePen.

貝塞爾曲線

在過渡或者動畫效果中,咱們可能須要使用貝塞爾曲線 cubic-bezier 來控制動畫的步調。咱們能夠在這裏 設置不一樣的曲線並預覽,或者在這裏 查看一些經常使用的曲線 html5

動畫

屬性

  • animation-name:指定動畫的名稱
  • animation-duration:定義動畫的時長(ms | s)
  • animation-iteration-count:聲明動畫的迭代次數(number | infinite)
  • animation-direction:設置動畫播放的方向(normal | reverse | alternate | alternate-reverse)
  • animation-delay:延遲播放動畫
  • animation-timing-function:改變更畫的內部時序
  • animation-play-state:設置動畫的播放狀態(running | paused)
  • animation-fill-mode:動畫的填充模式,也就是動畫結束以後的狀態(normal | forwards | backwards | both),最終的顯示效果與 animation-direction 屬性有關
    live demo

JS動畫事件

  • animationstart:動畫開始
  • animationiteration:每次迭代開始
  • animationend:動畫結束

動畫延遲效果

給不一樣對象賦予必定的延遲時間,每每能夠造成一些有趣的動畫效果。這裏咱們要區分兩種延遲:web

  • 瀏覽器把動畫附加到元素上以後等待多久開始第一次迭代:animation-delay: <time>
  • 每次迭代開始前須要等待:重複關鍵幀
    animation delay
    /*假設一個小球來回滾動,每次在兩邊時停留800ms再繼續滾動,咱們能夠由如下動畫控制*/
    .ball {
      width: 50px;
      height: 50px;
      border-radius: 50%;
      background-color: orange;
      animation: move 2000ms infinite alternate;/*alternate 設置來回滾動*/
    }
    @keyframes move {
      0%,
      40% {
        transform: translateX(0);/*重複關鍵幀模擬延遲,2000ms × .4 = 800ms*/
      }
      60%,
      100% {
        transform: translateX(250px);/*重複關鍵幀模擬延遲,2000ms × .4 = 800ms*/
      }
    }
    複製代碼
    live demo

從中間幀開始執行動畫

若是animation-delay的值爲負,並且絕對值比animation-duration 小,那麼動畫將當即開始而且從中間的關鍵幀開始播放。例如,一個動畫時長爲 10s,延遲時間爲 -4s,那麼若是 animation-timing-functionlinear,則將從動畫的 40% 開始播放canvas

利用 box-shadow

利用 box-shadow 能夠建立爲單個元素建立多個 border。例如,咱們能夠利用這個屬性爲一個 loading 動畫添加多個小的圓圈。瀏覽器

  • 語法:box-shadow: h-shadow v-shadow blur spread color inset;
  • 例子
// 咱們經過變換box-shadow來交換正方形的位置
.spinner {
  position: absolute;
  /*border-radius: 50%; need width > 0 and height > 0*/
  width: 0;
  height: 0;
  box-shadow: 
    -30px -30px 0 40px #a593e0, 
    -30px 30px 0 40px #e0e3da,
    30px 30px 0 40px #fffff3, 
    30px -30px 0 40px #566270;
  animation: spin 3000ms infinite alternate;
}
複製代碼

利用僞元素

咱們注意到利用 box-shadow 屬性,全部「子元素」是綁定在「父元素」上且同時變化的。若是咱們不想引入多餘的 DOM 元素,同時又想「子元素」不與「父元素」同時進行變換,咱們能夠採用::after::before來建立。
ide

來看一些有趣的例子吧

利用上述知識寫的一些簡單的動畫(點擊查看源碼)
函數

動畫性能

講完了一些基礎知識,讓咱們進一步聊聊動畫渲染的性能。佈局

瀏覽器底層原理

瀏覽器的工做原理,請看 How Browsers Work: Behind the scenes of modern web browsers,寫的很詳盡,值得一讀。 性能

瀏覽器處理的過程很簡單:計算元素的樣式(從新計算樣式),生成每一個元素的幾何形狀和位置(佈局),繪製圖層中的每一個像素(初始化繪圖而且進行繪圖)而且將圖層繪製到屏幕上(圖層的合成)

瀏覽器內部

現代瀏覽器一般有兩個主要的線程:① main thread;② compositor thread

  • 主線程的主要職責是(維持一個RenderLayers):
    • 運行腳本
    • 計算 HTML 元素的 CSS 屬性
    • 頁面佈局
    • 把 DOM 元素繪製到一個或者多個位圖上
    • 把合成的位圖交給compositor thread
  • 合成線程的主要職責是(維持一個 GraphicsLayers):
    • 經過 GPU 把位圖繪製到屏幕上
    • 請求主線程更新呈如今屏幕上或者即將呈如今屏幕上的位圖
    • 當進行滾動操做時,弄清楚哪部分即將呈如今屏幕上
    • 當進行滾動的時候,移動相應部分的頁面

合成線程會盡量響應用戶的鼠標鍵盤等消息事件。可能發生的狀況是,當頁面滾動須要更新視圖時,合成線程以每幀(60fps)請求更新位圖(刷新屏幕),但主線程上可能正進行復雜的腳本運算或者HTML元素繪製,致使合成線程沒法及時拿到位圖,這時合成線程會繪製空白。

GPU

GPU 可以很快地處理將位圖繪製到屏幕上的操做,還能很快處理將同一位圖經過變換再次繪製的操做,可是對於從內存中加載位圖的處理比較慢。比較一個過渡效果使用 height 和 transform 的兩個流程:

composited layer 建立的條件

  • 使用視頻加速解碼的 video 元素
  • flash、使用3D (WebGL) context 的 canvas 元素
  • CSS transform
  • CSS filter
  • CSS opacity

高性能的 CSS動畫

減小消耗成本

爲何有些動畫播放流暢,有些則顯得很卡頓呢?從上面的知識中,咱們或許會獲得一些啓發:現代瀏覽器在完成 position(位置), scale(比例縮放), rotation(旋轉) 和 opacity(透明度)這四種屬性的動畫時,消耗成本較低。

若是咱們使用 height 進行變換,瀏覽器可能在每幀須要請求主線程從新佈局、繪製和更新位圖,再將位圖從 CPU 傳給 GPU,這個過程可能致使卡頓,也就是咱們丟失了某些關鍵幀。

可是使用 height 的性能就必定比 transform 的性能差?不必定,可能的狀況是:① 繪製的位圖很小;② height 更新不會影響其餘元素的佈局等狀況;③ 元素是脫離正常流的;

咱們在使用 width、display、font-size、box-shadow、color 等可能引發重排或者重繪的屬性時,若是你不能清楚的知道本身在作什麼,咱們仍是建議使用推薦的操做避免糟糕的狀況出現。

JS動畫和CSS動畫的優缺點

  • 優勢:JavaScript中的動畫能夠爲你提供更多的控制,好比開始,暫停,回放,中斷和取消等,還能夠進行設計複雜的動畫效果。缺點:主線程上可能進行復雜的運算,增大掉幀的風險(咱們也能夠放在 Web Worker 中進行)。
  • 優勢:瀏覽器會對CSS動畫進行優化,若是有須要,它會建立圖層,而且能夠在主進程以外完成一些操做。缺點就是CSS動畫相對於Javascript動畫而言,缺少表現力,對動畫的設計來講更加複雜。

參考博客及推薦閱讀

相關文章
相關標籤/搜索