符合物理原理的加/減速

網頁功能: linear() 轉場效果

傳統 CSS 轉速函式 (例如 ease-in 或 cubic-bezier()) 僅限於簡單曲線,無法建立複雜的物理效果,例如彈跳或彈簧。linear() 時間函式可解決這個問題,讓您提供一系列停靠點,近似複雜曲線。轉場和動畫會根據停靠點之間的直線進行內插,但只要停靠點夠多,就能呈現流暢的效果。

導入步驟

  1. 產生曲線停靠點: 手動繪製數十個點來呈現彈簧或彈跳效果並不實際。請使用外部程式庫的時間函式,或使用工具將現有的 JavaScript 緩動函式或 SVG 路徑轉換為 linear() 語法。選用:將這些時間函式儲存為 CSS 自訂屬性,以便在整個網站中重複使用。
  2. 定義時間函式: 將產生的停靠點套用至 transition-timing-function 或 animation-timing-function 屬性,或透過 transition 或 animation 簡寫套用。
  3. 調整持續時間: JavaScript 物理引擎會根據物理屬性 (質量、剛度) 推算持續時間,但 CSS 仍需要固定的 duration。你可能需要調整時間長度,才能達到預期效果。

範例:彈簧緩動

這個範例說明如何使用自訂 linear() 函式,建立在穩定前超過目標值的彈簧效果。

.spring {
  /* Define the physics-based easing as a reusable variable */
  --spring-easing: linear(0, 0.016 0.5%, 0.06 1%, 0.226 2%, 1.116 5.4%, 1.375 6.6%, 1.527 7.7%, 1.565 8.2%, 1.585 8.8%, 1.581 9.3%, 1.559 9.8%, 1.458 10.9%, 0.937 14.3%, 0.784 15.5%, 0.693 16.6%, 0.67 17.1%, 0.657 17.7%, 0.671 18.7%, 0.729 19.8%, 1.042 23.3%, 1.13 24.5%, 1.182 25.6%, 1.201 26.7%, 1.192 27.7%, 1.156 28.8%, 0.977 32.2%, 0.925 33.4%, 0.894 34.5%, 0.882 35.6%, 0.887 36.6%, 0.907 37.7%, 1.045 42.4%, 1.069 44.5%, 1.059 46.3%, 0.979 50.9%, 0.96 53.4%, 0.966 55.3%, 1.013 59.9%, 1.024 62.3%, 0.986 71.2%, 1.008 79.9%, 0.995 88.9%, 1);


  /* Apply the easing with a duration that fits the spring's complexity */
  /* MANDATORY: Always include a duration; linear() does not calculate it automatically */
  transition: scale 0.8s var(--spring-easing);
}

.spring:hover {
  scale: 1.2;
}

範例:彈跳緩動

這個範例說明如何使用自訂 linear() 函式建立彈跳效果。

.bounce {
  /* Define the physics-based easing as a reusable variable */
  --bounce-easing: linear(0, 0.214 14.7%, 0.386 23.7%, 0.598 31.9%, 0.999 44.7%, 0.807 52.6%, 0.762 56%, 0.747 59.4%, 0.758 62.4%, 0.793 65.6%, 0.999 77.4%, 0.961 81.2%, 0.949 84.8%, 0.956 88%, 0.993 95.5%, 1);


  /* Apply the easing with a duration that fits the bounce's complexity */
  /* MANDATORY: Always include a duration; linear() does not calculate it automatically */
  transition: scale 0.4s var(--bounce-easing);
}

.bounce:hover {
  scale: 1.2;
}

考量重點

  • 效能:如要讓物理基礎動畫最流暢,請將 linear() 套用至在獨立執行緒上執行的屬性,例如 transform 和 opacity。
  • 精確度與酬載:雖然停靠點越多,曲線越平滑,但 CSS 的大小也會增加。多數產生器可讓您「簡化」曲線,在流暢度和程式碼大小之間取得最佳平衡。
  • 避免對彈跳效果使用不透明度:如果對 opacity 套用彈跳效果,當值超過 0 或 1 時,可能會造成視覺上不協調的閃爍。
  • 無障礙功能:複雜的物理動畫可能會分散某些使用者的注意力,或造成動態敏感。請務必尊重使用者偏好,減少或停用這些動畫。
@media (prefers-reduced-motion: reduce) {
  .element {
    transition: none;
  }
}

備用策略

CSS 備用廣告

如果瀏覽器不支援 linear(),請提供標準加/減速函式做為備用。如果瀏覽器無法辨識 linear() 值,就會忽略該值,並改用先前的有效宣告。

.element {
  /* Fallback for older browsers (standard smooth exit) */
  transition: transform 0.8s ease-out;
  
  /* Modern browsers will override with the physics-based easing */
  transition-timing-function: linear(0, 1.1, 0.95, 1.02, 1);
}

JavaScript 程式庫備用 (Motion/GSAP)

選用:如果高擬真物理動畫在舊版瀏覽器中也至關重要,請使用 Motion (motion.dev) 或 GSAP (greensock.com) 等 JavaScript 程式庫,在不支援 linear() 時處理動畫。

  1. 偵測支援:使用 CSS.supports() 檢查瀏覽器是否處理 linear() 函式。
  2. 有條件地載入/套用:如果不支援,請使用程式庫的彈簧或彈跳實作。
/* Detect if the browser supports the linear() function */
const supportsLinearEasing = window.CSS && CSS.supports('animation-timing-function', 'linear(0, 1)');

if (!supportsLinearEasing) {
  /* 
     Example using Motion (motion.dev) for a spring fallback.
     This should only be initialized if native CSS support is missing.
  */
  import("https://cdn.jsdelivr.net/npm/motion@latest/dist/motion.js").then(({ animate, spring }) => {
    animate(".element", { transform: "scale(1.2)" }, {
      easing: spring({ stiffness: 100, damping: 10 })
    });
  });
}

您也可以在 CSS 中使用 @supports,更明確地偵測功能:

@supports not (animation-timing-function: linear(0, 1)) {
  .element {
    /* Alternative experience for unsupported browsers */
    transition-duration: 0.4s;
    transition-timing-function: cubic-bezier(0.34, 1.56, 0.64, 1);
  }
}