CSS 動畫專題

SRIGT發表於2024-07-23

0x01 過渡 transition

  • 過渡(transition)是應用於特定元素的 CSS 屬性,在指定時間內平滑過渡到目標樣式

(1)必要屬性

  • 使用 transition-property 指定需要過渡的 CSS 屬性
    • 可以列入一個或多個 CSS 屬性
    • 也可以使用 all 值,表示所有變化的 CSS 屬性都需要過渡
    • 僅可以用於過渡的值是可以用數字表示的屬性,瀏覽器會計算並插入中間值實現過渡
  • 使用 transition-duration 指定過渡需要的持續時間
<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <style>
    button {
      width: 200px;
      height: 100px;
      font-size: 20px;
      border: none;
      color: white;
      background-color: red;
      cursor: pointer;

      transition-property: background-color;
      transition-duration: 1s;
    }

    button:hover {
      background-color: purple;
    }
  </style>
</head>

<body>
  <button>Button</button>
</body>

</html>

(2)其他屬性

  • 使用 transition-timing-function 指定過渡的時序函式(指過渡的變化方式)
    • ease:慢入、快變、慢出(預設)
    • linear:勻速
    • ease-in:緩慢開始,結束前加快
    • ease-out:快速開始,結束前減慢
    • ease-in-out:與 ease 類似
  • 使用 transition-delay 指定過渡的延遲時間
<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <style>
    button {
      width: 200px;
      height: 100px;
      font-size: 20px;
      border: none;
      color: white;
      background-color: red;
      cursor: pointer;

      transition-property: background-color;
      transition-duration: 1s;

      transition-timing-function: ease-in;
      transition-delay: 0.5s;
    }

    button:hover {
      background-color: purple;
    }
  </style>
</head>

<body>
  <button>Button</button>
</body>

</html>

(3)縮寫屬性

transition: property duration timing-function delay[, property duration timing-function delay];

0x02 變換 transform

  • 變換(transform)是指改變元素的尺寸、形狀以及位置
  • 變換提供了 4 種函式來控制元素的顯示方式:scaletranslaterotateskew
  • transform-origin:設定變換原點
    • 預設取值包括 topleftrightbottomcenter 以及 top lefttop rightbottom rightbottom left
    • 也可以透過百分比、數值分別設定在 \(x\)\(y\) 軸構成的座標

(1)scale

  • 透過放縮元素的寬高,改變元素的尺寸
  • scaleX():改變元素寬度,大於 \(1\) 表示放大倍數,\(0-1\) 之間表示縮小倍率(下同)
  • scaleY():改變元素高度
  • scale():一個值表示同時改變元素的寬高,兩個值表示同時分別改變元素的寬度與高度
<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <style>
    div {
      width: 300px;
      height: 200px;
      display: block;
      margin: auto;
      background-color: #ff7777;
      transition: transform 1s linear;
    }

    div:hover {
      transform: scale(1.5, 0.5);
    }
  </style>
</head>

<body>
  <div></div>
</body>

</html>

(2)translate

  • 透過平移的方式,改變元素的位置

  • 二維變換

    • translateX():沿 \(x\) 軸方向移動,正值向右、負值向左
    • translateY():沿 \(y\) 軸方向移動,正值向下、負值向上
    • translate(x, y):同時沿 \(x\)\(y\) 軸移動,第一個引數是 \(x\) 軸方向移動,第二個引數是 \(y\) 軸方向移動
    <!DOCTYPE html>
    <html>
    
    <head>
      <meta charset="UTF-8">
      <style>
        div {
          width: 300px;
          height: 200px;
          display: block;
          margin: auto;
          background-color: #ff7777;
          transition: transform 1s linear;
        }
    
        div:hover {
          transform: translate(-100px, 100px);
        }
      </style>
    </head>
    
    <body>
      <div></div>
    </body>
    
    </html>
    
  • 三維變換

    • translateZ():沿 \(z\) 軸方向移動,正值向外、負值向內
    <!DOCTYPE html>
    <html>
    
    <head>
      <meta charset="UTF-8">
      <style>
        body {
          perspective: 1000px;	// 設定人眼與螢幕的距離為 1000px(即人眼在 z 軸 1000px 處)
        }
    
        div {
          width: 300px;
          height: 200px;
          display: block;
          margin: auto;
          background-color: #ff7777;
          transform-origin: bottom left;
          transition: transform 1s linear;
        }
    
        div:hover {
          transform: translateZ(300px);	// 效果看起來是放大(即近大遠小)大於到人眼的距離時會消失
        }
      </style>
    </head>
    
    <body>
      <div></div>
    </body>
    
    </html>
    

(3)rotate

  • 透過旋轉,改變元素的角度

  • 二維變換

    • rotate():預設以元素中心為中心,旋轉指定角度(deg)、指定梯度(grad)或旋轉圈數(turn),正值順時針、負值逆時針
    <!DOCTYPE html>
    <html>
    
    <head>
      <meta charset="UTF-8">
      <style>
        div {
          width: 300px;
          height: 200px;
          display: block;
          margin: auto;
          background-color: #ff7777;
          transition: transform 1s linear;
        }
    
        div:hover {
          transform: rotate(1turn);
        }
      </style>
    </head>
    
    <body>
      <div></div>
    </body>
    
    </html>
    
  • 三維變換

    • rotateX():沿 \(x\) 軸旋轉,正負值旋轉方向不同(下同)
    • rotateY():沿 \(y\) 軸旋轉
    • rotateZ():沿 \(z\) 軸旋轉
    <!DOCTYPE html>
    <html>
    
    <head>
      <meta charset="UTF-8">
      <style>
        body {
          perspective: 1000px;
        }
    
        div {
          width: 300px;
          height: 200px;
          display: block;
          margin: auto;
          background-color: #ff7777;
          transition: transform 1s linear;
        }
    
        div:hover {
          transform: rotateX(30deg);
        }
      </style>
    </head>
    
    <body>
      <div></div>
    </body>
    
    </html>
    

(4)skew

  • 透過根據 \(x\) 軸或 \(y\)傾斜,改變元素的形狀
  • skewX():在 \(x\) 軸方向上傾斜指定角度,正負值方向不同(下同)
  • skewX():在 \(y\) 軸方向上傾斜指定角度
  • skew(x, y):同時分別改變元素在 \(x\)\(y\) 軸上的傾斜
<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <style>
    body {
      perspective: 1000px;
    }

    div {
      width: 300px;
      height: 200px;
      display: block;
      margin: auto;
      background-color: #ff7777;
      transition: transform 1s linear;
    }

    div:hover {
      transform: skewX(30deg);
    }
  </style>
</head>

<body>
  <div></div>
</body>

</html>

(5)案例

a. 旋入

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <style>
    body {
      height: 100vh;
      display: flex;
    }

    a {
      text-decoration: none;
      margin: auto;
      border: 3px solid black;
      padding: 30px 80px;
      font-size: 30px;
      font-weight: bolder;
      position: relative;
      overflow: hidden;
    }

    a::before {
      content: "";
      position: absolute;
      top: 0;
      left: 0;
      width: 105%;
      height: 100%;
      background-color: #ff7777;
      z-index: -1;
      transition: transform 0.5s ease-out;
      transform-origin: bottom left;
      transform: rotate(-90deg);
    }

    a:hover::before {
      transform: rotate(0deg);
    }
  </style>
</head>

<body>
  <a>Hover me</a>
</body>

</html>

b. 滑入

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <style>
    body {
      height: 100vh;
      display: flex;
    }

    a {
      text-decoration: none;
      margin: auto;
      border: 3px solid black;
      padding: 30px 80px;
      font-size: 30px;
      font-weight: bolder;
      color: #ff7777;
      position: relative;
      overflow: hidden;
      transition: all 1s ease-out;
    }

    a::before {
      content: "";
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background-color: #ff7777;
      z-index: -1;
      transition: all 0.5s ease-out;
      transform: translateX(-100%);
    }

    a:hover {
      color: white;
    }

    a:hover::before {
      transform: translateX(0);
    }
  </style>
</head>

<body>
  <a>Hover me</a>
</body>

</html>
  • 帶入文字

    <!DOCTYPE html>
    <html>
    
    <head>
      <meta charset="UTF-8">
      <style>
        body {
          height: 100vh;
          display: flex;
        }
    
        a {
          text-decoration: none;
          margin: auto;
          border: 3px solid black;
          padding: 30px 80px;
          font-size: 30px;
          font-weight: bolder;
          color: #ff7777;
          position: relative;
          overflow: hidden;
        }
    
        a::before {
          content: "YEAH!";
          position: absolute;
          top: 0;
          left: 0;
          width: 100%;
          height: 100%;
          background-color: #ff7777;
          color: white;
          transition: all 0.5s ease-out;
          transform: translateY(-100%);
    
          display: flex;
          align-items: center;
          justify-content: center;
        }
    
        a:hover::before {
          transform: translateY(0);
        }
      </style>
    </head>
    
    <body>
      <a>Hover me</a>
    </body>
    
    </html>
    
  • 偽閃光滑入

    <!DOCTYPE html>
    <html>
    
    <head>
      <meta charset="UTF-8">
      <style>
        body {
          height: 100vh;
          background-color: #333;
          display: flex;
        }
    
        a {
          text-decoration: none;
          margin: auto;
          border: 3px solid black;
          padding: 30px 80px;
          font-size: 30px;
          font-weight: bolder;
          color: #ff7777;
          position: relative;
          overflow: hidden;
          transition: all 0.5s ease-out;
        }
    
        a::before {
          content: "";
          position: absolute;
          top: 0;
          left: 0;
          width: 100%;
          height: 50%;
          background-color: white;
          z-index: -1;
          transition: all 0.5s ease-out;
          transform: translateX(-100%) rotate(45deg);
        }
    
        a:hover {
          background-color: #ff7777;
          color: white;
        }
    
        a:hover::before {
          transform: translateX(100%) rotate(45deg);
        }
      </style>
    </head>
    
    <body>
      <a>Hover me</a>
    </body>
    
    </html>
    

c. 十字擴充套件(三維變換)

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <style>
    body {
      height: 100vh;
      display: flex;
    }

    a {
      text-decoration: none;
      margin: auto;
      border: 3px solid black;
      padding: 30px 80px;
      font-size: 30px;
      font-weight: bolder;
      color: #ff7777;
      position: relative;
      overflow: hidden;
      transition: all 1s ease-out;
    }

    a::before,
    a::after {
      content: "";
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background-color: #ff7777;
      z-index: -1;
      transition: all 0.5s ease-out;
    }

    a::before {
      transform: rotateX(90deg);
    }

    a::after {
      transform: rotateY(90deg);
    }

    a:hover {
      color: white;
    }

    a:hover::before {
      transform: rotateX(0);
    }

    a:hover::after {
      transform: rotateY(0);
    }
  </style>
</head>

<body>
  <a>Hover me</a>
</body>

</html>
  • 文字放大退出

    <!DOCTYPE html>
    <html>
    
    <head>
      <meta charset="UTF-8">
      <style>
        body {
          height: 100vh;
          display: flex;
        }
    
        a {
          perspective: 500px;
          text-decoration: none;
          margin: auto;
          border: 3px solid black;
          padding: 30px 80px;
          font-size: 30px;
          font-weight: bolder;
          color: #ff7777;
          position: relative;
          overflow: hidden;
          transition: all 0.5s ease-out;
        }
    
        a::before {
          content: "Hover me";
          font-size: 30px;
          font-weight: bolder;
          color: white;
          position: absolute;
          top: 0;
          left: 0;
          width: 100%;
          height: 100%;
          background-color: #ff7777;
          z-index: -1;
          transition: all 0.5s ease-out;
          transform: translateZ(800px);
          display: flex;
          align-items: center;
          justify-content: center;
        }
    
        a:hover {
          color: white;
        }
    
        a:hover::before {
          transform: translateZ(0);
        }
      </style>
    </head>
    
    <body>
      <a>Hover me</a>
    </body>
    
    </html>
    
  • 切牌

    <!DOCTYPE html>
    <html>
    
    <head>
      <meta charset="UTF-8">
      <style>
        body {
          height: 100vh;
          display: flex;
        }
    
        a {
          text-decoration: none;
          margin: auto;
          border: 3px solid black;
          padding: 30px 80px;
          font-size: 30px;
          font-weight: bolder;
          color: transparent;
          position: relative;
          overflow: hidden;
        }
    
        a::before,
        a::after {
          content: "Hover me";
          font-size: 30px;
          font-weight: bolder;
          color: white;
          position: absolute;
          top: 0;
          width: 100%;
          height: 100%;
          background-color: #ff7777;
          transition: all 0.5s ease-out;
          display: flex;
          align-items: center;
          justify-content: center;
        }
    
        a::before {
          left: 0;
        }
    
        a::after {
          left: -100%;
        }
    
        a::before {
          transform: rotateY(0deg) scale(1);
        }
    
        a::after {
          transform: rotateY(360deg) scale(0);
        }
    
        a:hover::before {
          left: 100%;
          transform: rotateY(360deg) scale(0);
          opacity: 0;
        }
    
        a:hover::after {
          left: 0;
          transform: rotateY(0) scale(1);
          opacity: 1;
        }
      </style>
    </head>
    
    <body>
      <a>Hover me</a>
    </body>
    
    </html>
    

d. 點入後放大

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <style>
    body {
      height: 100vh;
      display: flex;
    }

    a {
      text-decoration: none;
      margin: auto;
      padding: 30px;
      font-size: 30px;
      font-weight: bolder;
      color: #ff7777;
      position: relative;
      overflow: hidden;
      transition: all 0.5s ease-out 0.5s;
    }

    a::before,
    a::after {
      content: "";
      position: absolute;
      top: 50%;
      width: 20px;
      height: 20px;
      border-radius: 50%;
      transform: translateY(-50%);
      background-color: transparent;
      z-index: -1;
      transition: all 0.5s ease-out;
    }

    a::before {
      left: 0;
      box-shadow: -100px 0 0 #ff7777;
    }

    a::after {
      right: 0;
      box-shadow: 100px 0 0 #ff7777;
    }

    a:hover {
      color: white;
      background-color: #ff7777;
    }

    a:hover::before {
      left: 50%;
      background-color: #ff7777;
      box-shadow: -30px 0 0 #ff7777;
      transform: translateX(-50%) translateY(-50%);
    }

    a:hover::after {
      right: 50%;
      background-color: #ff7777;
      box-shadow: 30px 0 0 #ff7777;
      transform: translateX(50%) translateY(-50%);
    }
  </style>
</head>

<body>
  <a>Hover me</a>
</body>

</html>

f. 取景框

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <style>
    body {
      height: 100vh;
      display: flex;
    }

    a {
      text-decoration: none;
      margin: auto;
      padding: 30px;
      font-size: 30px;
      font-weight: bolder;
      color: #ff7777;
      position: relative;
      transition: all 0.5s ease-out 0.5s;
    }

    a::before,
    a::after {
      content: "";
      position: absolute;
      width: 30px;
      height: 30px;
      background-color: transparent;
      z-index: -1;
      transition: all 0.5s ease-out;
    }

    a::before {
      top: -5px;
      left: -5px;
      border-top: 3px solid #ff7777;
      border-left: 3px solid #ff7777;
    }

    a::after {
      right: -5px;
      bottom: -5px;
      border-right: 3px solid #ff7777;
      border-bottom: 3px solid #ff7777;
    }

    a:hover {
      color: white;
      background-color: #ff7777;
    }

    a:hover::before,
    a:hover::after {
      width: 100%;
      height: 100%;
    }
  </style>
</head>

<body>
  <a>Hover me</a>
</body>

</html>

0x03 動畫與關鍵幀 animation & keyframes

(1)基本使用

  • 使用步驟:
    1. 定義 CSS 動畫規則(即關鍵幀)
    2. 將該動畫新增到需要動畫的元素上
  • @keyframes identifier:定義關鍵幀
  • animation-name:透過名稱使用相應的動畫
  • animation-duration:動畫持續時間
<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <style>
    div {
      width: 100px;
      height: 100px;
      display: block;
      background-color: #ff7777;
    }

    div:hover {
      animation-name: moving;
      animation-duration: 3s;
    }

    @keyframes moving {
      0% {
        transform: translate(0);
      }

      30% {
        transform: translate(150px);
      }

      100% {
        transform: translate(300px);
      }
    }
  </style>
</head>

<body>
  <div></div>
</body>

</html>

(2)其他屬性

  • animation-fill-mode:填充模式,設定 CSS 動畫在執行之前和之後如何將樣式應用於其目標(詳解
    • noneforwardbackwardboth
  • animation-iteration-count:迭代次數,設定 CSS 動畫重複執行次數
    • 取值 infinite 表示無限重複
  • animation-timing-function:時序函式,與 transition-timing-function 類似
  • animation-direction:動畫方向
    • reverse:逆向
    • alternate:交替
    • alternate-reverse:逆向交替
  • animation-delay:延時

(3)縮寫屬性

animation: name duration ...args

  • ...args 表示其他屬性,沒有規定順序

(4)案例:牛頓擺

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <style>
    body {
      height: 100vh;
      background-color: #333;
      display: flex;
      align-items: center;
      justify-content: center;
    }

    div {
      display: flex;
      border-top: 10px solid white;
    }

    span {
      display: block;
      width: 3px;
      height: 300px;
      background-color: white;
      margin: 0 30px;
      position: relative;
      transform-origin: top;
    }

    span::before {
      content: '';
      position: absolute;
      left: 0;
      bottom: 0;
      width: 60px;
      aspect-ratio: 1;
      border-radius: 50%;
      background-color: white;
      transform: translateX(-50%);
    }

    span:first-child {
      animation: left 2s ease-in infinite;
    }

    span:last-child {
      animation: right 2s ease-in infinite;
    }

    @keyframes left {
      0% { transform: rotate(0deg); }
      25% { transform: rotate(60deg); }
      50% { transform: rotate(0deg); }
      100% { transform: rotate(0deg); }
    }

    @keyframes right {
      0% { transform: rotate(0deg); }
      50% { transform: rotate(0deg); }
      75% { transform: rotate(-60deg); }
      100% { transform: rotate(0deg); }
    }
  </style>
</head>

<body>
  <div>
    <span></span>
    <span></span>
    <span></span>
    <span></span>
    <span></span>
  </div>
</body>

</html>

-End-

相關文章