canvas學習筆記-貝塞爾曲線

3.4 貝塞爾曲線

canvas提供了兩個繪製貝塞爾曲線api:

  • ctx.quadraticCurveTo(cpx, cpy, x, y);

二次貝塞爾曲線,(cpx, cpy)控制點 (x, y)終點

  • ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);

三次貝塞爾曲線,(cp1x, cp1y)控制點一, (cp2x, cp2y)控制點二, (x, y)終點

題外話:

貝塞爾曲線的數學基礎是早在 1912 年就廣爲人知的伯恩斯坦多項式。最早用來輔助汽車車體的工業設計。
CSS3的transition-timing-function屬性,取值就可以設置爲一個三次貝塞爾曲線方程transition-timing-function: cubic-bezier(0.1, 0.7, 1.0, 0.1)

canvas繪圖示例:

// 二次
ctx.moveTo(200, 100);
ctx.quadraticCurveTo(230, 250, 350, 200);
// 三次
ctx.moveTo(450, 250);
ctx.bezierCurveTo(530, 150, 650, 300, 700, 200);

藍色是控制點

clipboard.png

問題一:
那canvas是如何通過控制點來繪製出曲線的,或者如果不用這個,自己繪製曲線該如何操作呢:

這個是n階貝塞爾曲線的方程:

clipboard.png

我們重點看二(三)階方程:

clipboard.png

B(t)是曲線上的點,t在0~1之間取值, P0起始點,P2終點,P1控制點
t從0~1之間取值不斷增大,B(t)不斷取出曲線上的點,從P0移至P1
const bx = (1-t)*(1-t)*start.x + 2*t*(1-t)*control.x + t*t*end.x;
const by = (1-t)*(1-t)*start.y + 2*t*(1-t)*control.y + t*t*end.y;

clipboard.png

問題二:
我咋知道控制點該怎麼選,特別是起終點動態數據時(也就是說,我們使用時,往往只知道起點P0終點P1):

這個根據曲線斜率,可視化需求可能選取的方式不一致,不過大致原理相似
可以在起點和終點的垂直平分線上選一點作爲控制點, 然後用一個參數來控制曲線的彎曲程度
// curveness 彎曲程度(0-1)
const cp = {
  x: ( start.x + end.x ) / 2 - ( start.y - end.y ) * curveness,
  y: ( start.y + end.y ) / 2 - ( end.x - start.x ) * curveness
};

clipboard.png

題外話:

關於cp點的求解:
線段中點:
const mid = [ ( start.x + end.x) / 2, ( start.y + end.y ) / 2 ];
根據起點和終點也可以得到一個向量v:
const v = [ end.x - start.x, end.y- start.y ];
將這個向量順時針旋轉90度,得到一個垂直於它的向量v2:
const v2 = [ v.y, -v.x ];
那麼中間控制點的座標爲(向量v2乘curveness加上中間點座標)

const cp = { x: mid.x + v2.x curveness, y: mid.y + v2.y curveness} =
{ x:( start.x + end.x ) / 2 - ( start.y - end.y ) * curveness,
y:( start.y + end.y ) / 2 - ( end.x - start.x ) * curveness}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章