基于Canvas的贝塞尔曲线详解


前言

贝塞尔曲线一直是计算机绘图中的重点,我们常见的PhotoShop和Svg图片等和网页上的图片啊之类的就大量使用了贝塞尔曲线。该文使用html5中的Canvas标签,由特点、原理、实例等各个方面深入研究了贝塞尔曲线的应用与意义。


一、基本简介

贝塞尔曲线是应用于二维图形应用程序的数学曲线。曲线的定义有四个点:起始点、终止点(也称锚点)以及两个相互分离的中间点。滑动两个中间点,贝塞尔曲线的形状会发生变化。二十世纪六十年代晚期,PierreBézier应用数学方法为雷诺公司的汽车制造业描绘出了贝塞尔曲线。

二、一些特点

  1. 有起始点;
  2. 由连续的控制点{P0,P1,…Pn-1}控制曲线的形状;
  3. 描绘的线段一般不经过控制点。

三、一个例子

二次贝塞尔曲线
在这里插入图片
起始点坐标P1(50,50),P2(50,200)
控制点坐标P3(200,200)
该曲线整体划分为200(随机个数)个点,当前图片取得是第80个点
在线段P1P2和P2P3上取得D和F点,使得: P 1 D P 1 P 2 = P 2 F P 2 P 3   , {P_1D \over P_1P_2} = {P_2F \over P_2P_3} \,, P1P2P1D=P2P3P2F, 在链接DF,并在线段DF上找到H点,使得: D H D F = P 1 D P 1 P 2 = P 2 F P 2 P 3   。 { DH \over DF } = { P_1D \over P_1P_2 } = {P_2F \over P_2P_3}\,。 DFDH=P1P2P1D=P2P3P2F
=>D(50,110),F(110,200),H(74,146)
H点即是第80个点的坐标,根据上述关系,找到所有200个点,就得到下图。
在这里插入图片描述
=>得到了一条曲线
=>贝塞尔曲线其实就是一系列点的集合(只要点够多,就越趋近线段)
下面展示一下一个一次,三次,四次,五次贝塞尔曲线的例子:

贝塞尔曲线示例
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

相应推导过程与上面二次贝塞尔的一样,只是需要更多步骤。

四、公式推导

给定一一个系数 t ∈ [ 0 , 1 ] t \in [0,1] t[0,1]

1、一次贝塞尔曲线

设P1坐标为(a,b),P2坐标为(c,d)
在线段P1P2上取得一点H(e,f),使得: t = P 1 H P 1 P 2 = ( e − a , f − b ) ( c − a , d − b )   t={P_1H \over P_1P_2} = {(e-a,f-b) \over (c-a,d-b)} \, t=P1P2P1H=(ca,db)(ea,fb)
=> { e = t ( c − a ) + a = t c + ( 1 − t ) a f = t ( d − b ) + b = t d + ( 1 − t ) b \begin{cases} e=t(c-a)+a=tc+(1-t)a \\ f=t(d-b)+b=td+(1-t)b \end{cases} {e=t(ca)+a=tc+(1t)af=t(db)+b=td+(1t)b
=> B ( t ) = ( P 2 − P 1 ) ∗ t + P 1 = ( 1 − t ) P 1 + t P 2 B(t)=(P_2-P_1)*t+P_1=(1-t)P_1+tP_2 B(t)=(P2P1)t+P1=(1t)P1+tP2
所以一次贝塞尔曲线中各点 B ( t ) B(t) B(t)为: ( P 2 − P 1 ) ∗ t + P 1 = ( 1 − t ) P 1 + t P 2 (P_2-P_1)*t+P_1=(1-t)P_1+tP_2 (P2P1)t+P1=(1t)P1+tP2

2、二次贝塞尔曲线

由例子部分内容及一次贝塞尔曲线公式:
=> { D = ( 1 − t ) P 1 + t P 2 F = ( 1 − t ) P 2 + t P 3 H = ( 1 − t ) D + t F \begin{cases} D=(1-t)P_1+tP_2 \\ F=(1-t)P_2+tP_3 \\ H=(1-t)D+tF \end{cases} D=(1t)P1+tP2F=(1t)P2+tP3H=(1t)D+tF
=> B ( t ) = H = ( 1 − t ) 2 p 1 + 2 t ( 1 − t ) P 2 + t 2 P 3 B(t)=H=(1-t)^2p_1+2t(1-t)P_2+t^2P_3 B(t)=H=(1t)2p1+2t(1t)P2+t2P3

同理可得三次,四次,五次贝塞尔曲线公式:

3、三次贝塞尔曲线

B ( t ) = ( 1 − t ) 3 P 1 + 3 t ( 1 − t ) 2 P 2 + 3 t 2 ( 1 − t ) P 3 + t 3 P 4 B(t)=(1-t)^3P_1+3t(1-t)^2P_2+3t^2(1-t)P_3+t^3P_4 B(t)=(1t)3P1+3t(1t)2P2+3t2(1t)P3+t3P4

4、四次贝塞尔曲线

B ( t ) = ( 1 − t ) 4 P 1 + 4 t ( 1 − t ) 3 P 2 + 6 t 2 ( 1 − t ) 2 P 3 + 4 t 3 ( 1 − t ) P 4 + t 4 P 5 B(t)=(1-t)^4P_1+4t(1-t)^3P_2+6t^2(1-t)^2P_3+4t^3(1-t)P_4+t^4P_5 B(t)=(1t)4P1+4t(1t)3P2+6t2(1t)2P3+4t3(1t)P4+t4P5

5、五次贝塞尔曲线

B ( t ) = ( 1 − t ) 5 P 1 + 5 t ( 1 − t ) 4 P 2 + 10 t 2 ( 1 − t ) 3 P 3 + 10 t 3 ( 1 − t ) 2 P 4 + 5 t 4 ( 1 − t ) P 5 + t 5 P 6 B(t)=(1-t)^5P_1+5t(1-t)^4P_2+10t^2(1-t)^3P_3+10t^3(1-t)^2P_4+5t^4(1-t)P_5+t^5P_6 B(t)=(1t)5P1+5t(1t)4P2+10t2(1t)3P3+10t3(1t)2P4+5t4(1t)P5+t5P6
由上述几个公式,研究规律,可以发现:

常数项 C = n ! i ! ( n − i ) ! , t ∈ [ 0 , n ]   C={n! \over i!(n-i)!} ,t\in[0,n]\, C=i!(ni)!n!,t[0,n](杨辉三角);

指数项 E t = i , i ∈ [ 0 , n ] E_t=i,i\in[0,n] Et=i,i[0,n]

指数项 E 1 − t = n − i , i ∈ [ 0 , 1 ] E_{1-t}=n-i,i \in[0,1] E1t=ni,i[0,1]

由上述规律,我们得到n阶贝塞尔曲线公式:

一般公式

B ( t ) = ∑ i = 0 n n ! i ! ( n − i ) ! t i ( 1 − t ) n − i P i = ( 1 − t ) n P 0 + n ! ( n − i ) ! t ( 1 − t ) n − 1 P 1 + . . . + t P n B(t)=\sum_{\mathclap{i=0}}^n {n! \over i!(n-i)!}t^i(1-t)^{n-i}P_i=(1-t)^nP_0+{n! \over (n-i)!}t(1-t)^{n-1}P_1+...+tP_n B(t)=i=0ni!(ni)!n!ti(1t)niPi=(1t)nP0+(ni)!n!t(1t)n1P1+...+tPn
由上述推导过程,可知不管几阶公式都是由一阶公式推导出来的:所以我们可以得到一个递推公式: P i k { P i , k = 0 ( 1 − t ) P i k − 1 + t P i + 1 k − 1 , k ∈ [ 1 , n − k ] P_i^k\begin{cases} P_i,k=0 \\ (1-t)P_i^{k-1}+tP_{i+1}^{k-1},k \in [1,n-k] \end{cases} Pik{Pi,k=0(1t)Pik1+tPi+1k1,k[1,nk]

五、一些实例

由公式推导的递推公式可知,不管多复杂的贝塞尔曲线,我们都可以拆分成一阶贝塞尔曲线。由此关系,我们在canvas中的曲线逻辑就有一个眉目了,下面是两个用贝塞尔曲线绘制的示意图片(canvas以为我们内置了两个函数quadraticCurveTo和bezierCurveTo,分别代表二次贝塞尔曲线和三次贝塞尔曲线)。

类别示例
头像在这里插入图片描述
小孩在这里插入图片描述

由此可见,贝塞尔曲线的功能是很强大的,而他的应用也特别广泛,例如PhotoShop软件,SVG图片等等,我们都能看见他们的身影。
上述所有图片项目地址:贝塞尔曲线Demo


一些建议

  1. 平常绘图等尽量使用2-3阶贝塞尔曲线;
  2. 超过3阶的曲线尽量降阶为2-3阶贝塞尔曲线;
  3. 贝塞尔曲线本质上是一系列点的集合,需要大量的计算。

总结

贝塞尔曲线功能强大,应用广泛。我们不仅可以使用它绘制图片,还能应用与各个领域,例如激光切割啊等等。就像实例中展示的那样,使用贝塞尔曲线,我们可以绘制各种各样的图形,为计算机的图形图像技术产生了深远意义上的影响。基于此,贝塞尔曲线具有很高的研究意义,为我们的社会进步和发展注入了一针强心剂。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
贝塞尔曲线是一种平滑的曲线,可以用于制作动画效果。在canvas中,我们可以使用贝塞尔曲线来绘制路径,并通过动画让路径呈现出流畅的变化。 下面是一个使用贝塞尔曲线实现动画效果的示例: ```html <canvas id="myCanvas" width="500" height="500"></canvas> ``` ```javascript // 获取canvas元素 var canvas = document.getElementById("myCanvas"); var ctx = canvas.getContext("2d"); // 定义起点、终点和控制点 var startPoint = {x: 50, y: 50}; var endPoint = {x: 450, y: 450}; var controlPoint = {x: 250, y: 50}; // 定义动画帧数和当前帧数 var frames = 60; var currentFrame = 0; // 绘制贝塞尔曲线路径 function drawBezierPath() { ctx.beginPath(); ctx.moveTo(startPoint.x, startPoint.y); ctx.quadraticCurveTo(controlPoint.x, controlPoint.y, endPoint.x, endPoint.y); ctx.stroke(); } // 清除canvas function clearCanvas() { ctx.clearRect(0, 0, canvas.width, canvas.height); } // 动画函数 function animate() { clearCanvas(); drawBezierPath(); currentFrame++; // 当前帧数小于动画帧数时,继续执行动画 if (currentFrame < frames) { controlPoint.y += 2; requestAnimationFrame(animate); } } // 启动动画 animate(); ``` 在这个示例中,我们定义了起点、终点和控制点的坐标,并使用`quadraticCurveTo()`方法绘制了贝塞尔曲线路径。然后定义了动画帧数和当前帧数,以及动画函数`animate()`。在动画函数中,我们清除canvas,重新绘制路径,将控制点的y坐标逐渐增加,实现动画效果。 你可以根据自己的需求修改起点、终点和控制点的坐标,以及动画帧数和控制点的移动方式,来实现不同的贝塞尔曲线动画效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lhuann_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值