canvas學習筆記-貝塞爾曲線

3.4 貝塞爾曲線

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

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

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

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

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

題外話:設計

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

canvas繪圖示例:code

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

藍色是控制點ip

clipboard.png

問題一:
那canvas是如何經過控制點來繪製出曲線的,或者若是不用這個,本身繪製曲線該如何操做呢:數學

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

clipboard.png

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

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):function

這個根據曲線斜率,可視化需求可能選取的方式不一致,不過大體原理類似
能夠在起點和終點的 垂直平分線上選一點做爲 控制點, 而後用一個參數來控制曲線的 彎曲程度
// 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}

相關文章
相關標籤/搜索