貝塞爾曲線又叫貝茲曲線,在大學高數中一度讓我非常頭疼。前陣子練手寫動畫的時候,發現貝塞爾曲線可以應用於軌跡的繪製以及定義動畫曲線。
本文就來探究一下,貝塞爾曲線到底是個什麼樣的存在。
貝塞爾曲線原理
貝塞爾曲線由n個點來決定,其曲線軌跡可以由一個公式來得出:
其中n就代表了貝塞爾曲線是幾階曲線,該公式描述了曲線運動的路徑。
以下我們來討論一下,貝塞爾公式如何推導。
一階貝塞爾曲線
設定圖中運動的點為Pt,t為運動時間,t∈(0,1),可得如下公式
二階貝塞爾曲線
在二階貝塞爾曲線中,已知三點恆定(P0,P1,P2),設定在P0P1中的點為Pa,在P1P2中的點為Pb,Pt在PaPb上的點,這三點都在相同時間t內做勻速運動。
由公式(1)可知
將公式(2)(3)代入公式(4)中,可得
三階貝塞爾曲線
同理,根據以上的推導過程可得
由此可以推導
n階貝塞爾曲線
放上一個網址,隨意感受一下貝塞爾曲線的繪製過程:
myst729.github.io/bezier-curv…
實際應用
貝塞爾曲線在前端中主要有兩方面的應用,一方面可以作為動畫曲線應用於CSS3動畫中;另一方面可以通過canvas來繪製曲線達到需要的效果。
CSS3中貝塞爾曲線的應用
在CSS3中,有兩屬性經常被用到:transition-timing-function
和animation-timing-function
,這兩個分別代表了過渡的速度和動畫的速度。CSS3為我們提供了一個新的工具——cubic-bezier(x1,y1,x2,y2)
。這個工具能夠生成一個速度曲線,使我們的元素按照該曲線來調節速度。
在上面的推導中,我們知道在貝塞爾公式中,有兩個點的位置恆定——P0和P1,cubic-bezier
中定義了兩個控制點的位置,所以該曲線為三階貝塞爾曲線。
有個網站可以方便我們快速建立一個貝塞爾曲線:cubic-bezier
貝塞爾曲線與動畫曲線的關聯
先來一波動圖簡單粗暴的感受一下: 例一:
例二:
例三:
左邊的是貝塞爾曲線,橫軸代表了事件,豎軸代表了進度,無法直觀得感受出速度的變化。
右邊的曲線是控制皮膚中的動畫曲線,橫軸是時間,豎軸是速度,可以方面地看出速度的變化。
上述例子中,以前進反向為速度正方向,後退方向為速度反方向。
如何得知速度的變化
推導
例一中,貝塞爾曲線為一條直線,當時間均勻變化時,進度也在均勻變大,由此可知速度恆定不變,時間和進度之間的關係可以用一個線性方程來表示:
y=ax+b (a=1,b=0)
複製程式碼
其中x為時間,y為進度,a即為速度。
推導案例一
從上面結論中啟發,去觀察其他貝塞爾曲線,
圖中是一段變化的曲線,我們取其中一小段,將其看作穩定不變的一段直線,通過下面的線性方程來表示,並通過紅線標註在圖中:
y=ax+b
複製程式碼
根據初中數學的內容,我們知道,當a>1時,與x軸的夾角∈(45°,90°);當a∈(0,1)時,與x軸的夾角在(0,45°)之間。相同的時間內,與x軸的夾角越大,a越大,速度越快。
觀察上圖的夾角變化趨勢,夾角逐漸變小趨向於0,而後逐漸變大,趨向於90°,對應速度應是速度逐漸變慢趨向於0,之後逐漸變快。
放上動畫曲線以及動圖來驗證一下我們的推測:
推導案例二
下圖中的曲線部分在第四象限,部分在第一象限,這時對應的動畫曲線該如何推導呢。
同樣將該曲線視為由n段平滑的直線構成,由線性方程來表示直線的趨勢,可知速度a方向一開始為負,之後慢慢向正方靠近,a的速率也在由大變小,當為0時,再向正方慢慢變大。即該曲線表示元素一開始在朝反方向減速運動,當速度為0後,向正方向作加速運動。
通過動畫曲線及動圖來驗證上述推導:
驗證
用兩個曲線來驗證一下上面的結論:
曲線一:
曲線二:
從結果可以判斷,用上述推導方法可以正確得出貝塞爾曲線與動畫曲線之間的關係。
動畫曲線的應用
瞭解瞭如何用貝塞爾曲線來指定動畫曲線後,很多動畫涉及到速度方面的效果就可以實現了,例如小車加速剎車,彈簧動畫等速度軌跡都可以根據自己的需要來進行定製。
放上一個緩動函式速查網址,可以讓自己的動效更加真實:緩動函式
放一個小例子:
該動畫模擬了小球落下回彈的過程
程式碼如下:
<div class="ground">
<div class="ball" id="ball"></div>
</div>
複製程式碼
.ball {
width: 30px;
height: 30px;
background: #000000;
border-radius: 50%;
position: absolute;
top: 0;
left: 50%;
animation: move 4s cubic-bezier(0.36, 1.7, 0.26, 0.61) 1s infinite;
}
@keyframes move {
0% {
top: 0;
}
100% {
top: 90%;
}
}
複製程式碼
這類動畫可以參考網上大大們的案例:
利用canvas繪製貝塞爾曲線
canvas中提供了api可以快速繪製一條貝塞爾曲線,來達到需要的效果:
二階貝塞爾曲線
quadraticCurveTo(x1,y1,x2,y2)
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.beginPath();
ctx.moveTo(20,20);
ctx.quadraticCurveTo(40,200,200,20);
ctx.stroke();
複製程式碼
其中moveTo
定義了起始點,quadraticCurveTo(x1,y1,x2,y2)
中的(x1,y1)
為控制點,(x2,y2)
為終點
三階貝塞爾曲線
bezierCurveTo(x1,y1,x2,y2,x3,y3)
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.beginPath();
ctx.moveTo(20,20);
ctx.bezierCurveTo(40,100,200,150,200,20);
ctx.stroke();
複製程式碼
其中moveTo
定義了起始點,bezierCurveTo(x1,y1,x2,y2)
中的(x1,y1)
,(x2,y2)
為控制點,(x3,y3)
為終點
總結
為了弄清貝塞爾曲線是個什麼東西,和動畫曲線、速度又有什麼關聯,作者跑去複習了一下那些早扔給老師的東西,有說錯的請輕拍/(ㄒoㄒ)/~~
廣而告之
本文釋出於薄荷前端週刊,歡迎Watch & Star ★,轉載請註明出處。
歡迎討論,點個贊再走吧 。◕‿◕。 ~
我的部落格即將同步至騰訊雲+社群,邀請大家一同入駐:cloud.tencent.com/developer/s…