CSS cubic-bezier() 數學解說:控制點、反函數及牛頓法
GDESIGN
設計發布: 10 分鐘閱讀

CSS cubic-bezier() 數學解說:控制點、反函數及牛頓法

在 CSS 過渡效果中設定 cubic-bezier(0.25, 0.1, 0.25, 1.0),四個數字各自代表甚麼?SVG 用貝塞爾曲線(Bézier curve)描繪形狀,CSS 則用同一類曲線將輸入進度對應至輸出進度。端點固定在 (0,0) 及 (1,1),兩個 x 控制座標必須介乎 0 與 1。本文解說這項限制的數學依據,以及如何用牛頓法或二分法反向求解。CSS Easing Functions 規範訂明輸出應如何計算,但沒有指定瀏覽器內部必須使用哪一種數值求解演算法。

日文原文發布: 2026-05-01

CSS 緩動曲線表示甚麼?

SVG 路徑描述平面上的形狀;CSS 緩動曲線則將兩種進度連繫起來:

  • x:輸入進度,通常是已經過的時間佔總時間的比例,由開始時的 0 增至結束時的 1。
  • y:輸出進度,用於在動畫屬性的起始值與結束值之間作插值。

P₀=(0,0) 及 P₃=(1,1) 是固定端點。cubic-bezier(x1, y1, x2, y2) 的四個引數指定 P₁=(x₁,y₁) 及 P₂=(x₂,y₂),共同定義一維對應 y=f(x)。

W3C 已發表的 CSS Easing Functions Level 2 工作草案在 §2.3 說明三次貝塞爾緩動函數。本文的數值方法只討論輸入進度 x ∈ [0,1]。CSS 對區間外的輸入亦有定義,會根據端點一側的控制點延伸輸出。曲線的參數 t 並非經過時間,而是計算曲線位置時使用的中間變數。

三次貝塞爾曲線與 Bernstein 基底

四個控制點決定一條三次貝塞爾曲線。當 t 在 0 至 1 之間,曲線上的點 B(t) 可寫成:

B(t) = (1-t)³ P₀ + 3(1-t)² t P₁ + 3(1-t) t² P₂ + t³ P₃

四個權重是三次的 Bernstein 基底多項式。透過二項式展開,可確認以下性質:

  • 非負:在 [0,1] 內,Bᵢ,ₙ(t) ≥ 0。
  • 單位分解(partition of unity):各項權重的總和等於 1。
  • 對稱:Bᵢ,ₙ(t)=Bₙ₋ᵢ,ₙ(1−t)。

權重非負而且總和為 1,表示 B(t) 是全部四個控制點的凸組合,曲線因而留在它們的凸包之內。這包括兩個固定端點,不能只取 P₁ 及 P₂。有效 CSS 曲線的四個 x 座標均在 [0,1],所以 x(t) 也在此範圍內。

x 控制座標限制如何保證單調性?

把固定端點代入後,x 座標的公式為:

x(t) = 3(1-t)² t · x₁ + 3(1-t) t² · x₂ + t³

要把 x 對應至 y,x 座標便不能沿曲線往回走,否則同一個輸入可能對應多個 t。對 t 求導數,可得:

x'(t) = 3[(1-t)² x₁ + 2(1-t)t(x₂-x₁) + t²(1-x₂)]

x₁,x₂ ∈ [0,1] 已足以保證導數非負,毋須另外要求 x₁ ≤ x₂。以下是推導:固定 t 後,x'(t)/3 是 x₁、x₂ 的仿射函數,因此單位正方形內的函數值,可寫成四個角點函數值的凸組合:

(x₁, x₂) = (0, 0): x'(t)/3 = t²
(x₁, x₂) = (0, 1): x'(t)/3 = 2t(1-t)
(x₁, x₂) = (1, 0): x'(t)/3 = (1-2t)²
(x₁, x₂) = (1, 1): x'(t)/3 = (1-t)²

四個結果均非負。由於 x(t) 不是常數多項式,其導數不可能在任何長度大於零的區間內一直為零。因此 x(t) 嚴格遞增,但某個位置的導數仍可等於零。例如 x₁=1、x₂=0 時,t=0.5 的導數為零,卻不影響反函數的唯一性。

CSS 並沒有對 y 控制座標施加同樣的 [0,1] 限制。例如 cubic-bezier(0.68, -0.55, 0.27, 1.55) 的輸出可低於 0 或高於 1,令動作先向反方向移動,再越過目標位置。

由輸入進度 x 反求參數 t

瀏覽器需要由當前輸入進度 x 求得輸出進度 y,但參數式直接給出的是 t → (x,y)。一般而言,不能直接把經過時間的比例當作 t 使用。

  1. 先解 x(t)=x,找出曲線參數 t。
  2. 再計算該 t 所對應的 y(t)。

第一步是三次方程式的求根問題。解析解是一個選項;實作亦可按精度、運算成本及特殊控制點附近的穩定性,選擇迭代方法。CSS 規範沒有要求使用某一種求根演算法。

牛頓法及二分法的適用條件

牛頓法(Newton–Raphson method)以下列公式反覆更新估計值,求解 x(t)−x_target=0:

t_next = t - (x(t) - x_target) / x'(t)

導數過小,可能令下一個估計值跳出 [0,1]。導數為零也不限於端點:x₁=1、x₂=0、t=0.5 就是區間內的例子。帶保護措施的求解器會檢查殘差、導數、新估計值及迭代次數上限;當牛頓法不適用時,可轉用二分法。

二分法每次將參數候選區間減半,利用 x(t) 的單調性,保持根位於區間內。它通常比牛頓法需要更多次迭代。NanToo 的 cubic-bezier 編輯器對區間內的預覽輸入採用 40 次二分,輸入進度為 0 或 1 時直接傳回端點。若以理想實數計算,剩餘區間寬度是 2⁻⁴⁰;這不保證經浮點數捨入後,y 也有相同精度。

工具操作範圍不等於 CSS 語法限制。編輯器把 x₁/x₂ 限制在 0 至 1、y₁/y₂ 限制在 −1 至 2,再把控制座標取至小數點後兩位;輸入進度亦限制在 0 至 1。它是有界範圍的預覽工具,並非驗證 CSS 區間外外推行為的通用求值器。

CSS 緩動關鍵字與控制座標

四個 ease 類關鍵字各自對應一條三次貝塞爾曲線。linear 則是另一個線性緩動關鍵字,輸出等於輸入。下表最後一行所列的曲線,具有相同的 y=x 輸出。

如表格未能完整顯示,可左右捲動。

關鍵字控制座標 (x₁,y₁,x₂,y₂)效果
ease(0.25, 0.1, 0.25, 1.0)起步較慢,中段加快,結束前減速
ease-in(0.42, 0, 1.0, 1.0)慢速起步,逐漸加速
ease-out(0, 0, 0.58, 1.0)快速起步,逐漸減速
ease-in-out(0.42, 0, 0.58, 1.0)起步及結束均較慢,兩端對稱
linear(0, 0, 1.0, 1.0)相同的等速輸出

transition-timing-function 的初始值為 ease。表中 linear 一行的曲線滿足 x(t)=y(t),但兩者一般都不等於 t。另須區分關鍵字 linear 與函數 linear():後者在多個點之間作分段線性插值。

單一三次曲線不能任意表達多次彈跳。y'(t) 是二次式,因此區間內最多只有兩個改變升降方向的位置。視乎所需動作,可採用 linear() 的折線近似、多個關鍵幀,或以 JavaScript 自行計算。

字體輪廓中的貝塞爾曲線

貝塞爾曲線亦可描述字形,而不只是控制動畫時間。

如表格未能完整顯示,可左右捲動。

輪廓格式曲線次數每段的點數起源
TrueType(Apple/Microsoft,1991)二次3 點:起點、控制點、終點Apple
OpenType CFF/Type 1 輪廓三次4 點:起點、兩個控制點、終點Adobe

TrueType 輪廓使用二次曲線,CFF 及 Type 1 輪廓使用三次曲線。OpenType 可容納這兩種輪廓表示方式。至於光柵化處理如何近似或細分曲線,則會因實作而有所不同。

Horner 求值與 de Casteljau 插值

已知 t 時,可以用不同方法求出曲線座標。第一種做法是展開座標多項式,再以 Horner 法計算。以下 JavaScript 適用於 CSS 固定端點下的 x(t):

const a = 3 * x1 - 3 * x2 + 1;
const b = -6 * x1 + 3 * x2;
const c = 3 * x1;
const x = ((a * t + b) * t + c) * t;

預先計算 a、b、c 後,每次求一個座標只需三次乘法及兩次加法。這個計數不包括係數的準備,也不包括反求 x(t) 所需的迭代。

另一種是 de Casteljau 演算法,逐層在相鄰點之間插值。這裏 lerp(A,B,t) 表示 (1−t)A+tB,對每個座標分別計算:

Q0 = lerp(P0, P1, t)
Q1 = lerp(P1, P2, t)
Q2 = lerp(P2, P3, t)
R0 = lerp(Q0, Q1, t)
R1 = lerp(Q1, Q2, t)
B  = lerp(R0, R1, t)

三次曲線需要六次插值,不代表只有六次乘法。即使 1−t 已經算好,單一座標的 (1-t)*a+t*b 仍包含兩次乘法及一次加法。Horner 法的算式較精簡,實際速度則取決於實作及執行環境。de Casteljau 法在 [0,1] 內反覆計算凸組合,適合穩定求值;但兩種方法都無法完全消除浮點數誤差。

重點整理

  • CSS 利用貝塞爾曲線把輸入進度對應至輸出進度。
  • 端點固定在 (0,0) 及 (1,1),四個引數指定另外兩個控制點。
  • x₁,x₂ ∈ [0,1] 保證反函數唯一,x₁ 大於 x₂ 也不例外。
  • CSS 允許 y 控制座標超出 [0,1],讓動作越過目標。
  • 由 x 找出 t,與已知 t 後計算曲線位置,是兩個不同步驟。
  • 牛頓法需要保護措施;二分法利用 x 座標的單調性,保留包含根的區間。
  • Bernstein 基底令曲線留在所有控制點的凸包內,包括固定端點。
  • 四個 ease 類關鍵字對應三次貝塞爾曲線;linear 是輸出等於輸入的獨立關鍵字。
  • TrueType 及 CFF 字體輪廓分別展示二次及三次貝塞爾曲線的應用。

參考資料及來源

編輯說明

本文使用 AI 協助編輯,並在發布前由編輯核對。內容仍可能包含事實、理解或時效上的錯誤;作出重要決定前,請查閱所列的一手資料或官方文件。

相關文章