canvas贝塞尔曲线动画,
写在最前
在上一篇文章中,我们提到了贝塞尔公式的应用。这次分享一下如何推导贝塞尔公式,并附上一个简单的例子,就是球遵循曲线轨迹。
效果预览
演示地址
关于如何绘制连续的贝塞尔曲线,可以参考这篇文章:基于canvas使用贝塞尔曲线平滑拟合断开的线段。
本例中生成的曲线由上述文章中的源代码提供。
贝塞尔曲线公式的推导
上图是贝塞尔曲线的完整公式,看起来很蠢==,因为这是n阶的求导公式,这次我们就通过一阶和二阶贝塞尔公式的求导来了解这个求导公式的由来。我们来看看网上流传已久的几张贝塞尔的图片:
这三张图中最重要的部分是我们需要了解变量t,t的取值范围是0-1。从上面的gif也可以看出,似乎曲线的绘制过程就是t从0到1的过程。嗯,其实就是这样。T的真正含义是什么?
在p0p1、p1p2、p2p3等中,每个环节都被分成两部分(仔细看动画中的黑、绿、蓝点)。每个环节中两部分的比例是一样的,从0到1不等,这个比例就是t。
看看下面的一阶贝塞尔曲线示意图:
是ptp0p1上的任意一点,p0pt/ptp1=t.所以我们可以引出下面的推导。
这时候t是时间,v是速度。我们可以把p0到p1的距离想成固定的速度乘以固定的时间。
因此,到达P上某一点的时间是固定速度乘以某一时间值。同时,固定速度已经可以表示为上面的推导公式。此时,方程右侧形成t (0,1)/t;也就是相当于某个时间值/固定时间值,也就是我们开头强调的变量T产生了,它的取值范围是[0,1]。因此,下面的等式更容易理解。
至此,我们已经推出了一阶贝塞尔曲线,其中的变量是起点、终点和比值t。
那么二阶公式如何从一阶过渡过去呢?
看看下面这张图:
Pp(t)的路径就是我们所寻求的二阶贝塞尔曲线,所以实际上我们也可以从一阶演化而来:
首先我们把两点pa和pb连接的线段看作一阶曲线,然后两端的一阶曲线分别代表pa和pb,最后我们得到我们的二阶曲线公式。仔细观察会发现,这与我们最初的完整公式相同:
当n取不同值时,可以得到不同的阶次曲线公式。同时,从上面的推导过程中我们也可以知道,无论曲线有多少条,我们都可以用一阶来表示,而这个“表示”过程就是我们上面看到的动画中的辅助线。所以你可以感受一下作者自己写的曲线形成的动画的效果,每个辅助线都是由一阶曲线形成的:
相关地址
对象遵循复杂的曲线轨迹。
当我们知道了曲线的公式从何而来,就很容易理解如何让球沿着曲线运动。我们生成的每一条曲线都可以用一个公式来表示,这就是为什么我们可以得到每一个t值处的曲线坐标。从而知道对象的绘图坐标。
//核心逻辑线性渐变。原型。drawball=function(){ var self=this var item=ctrlNodesArr[ctrlDrawIndex]//存储了各段曲线的控制点//各段曲线均为三阶贝塞尔,故下面计算x,y值代入到了三阶公式中var ctrlAx=item.cAx,//各个控制点ctrlAy=item.cAy,ctrlBx=item.cBx,ctrlBy=item.cBy,if(item.t 1) { ctrlDrawIndex //当一段曲线的一种网络的名称(传输率可达1.54mbps)级(一种通讯线路的名称)说明曲线已经走到头}else { self.ctx.clearRect(0,0,self.width,self。高度)项。t=0.05 var ballX=ox * math。pow((1项。t),3)3 * CTR lax * item。t *数学。pow((1项。t),2) 3 * ctrlBx * Math.pow(item.t,2) * (1 - item.t) x * Math.pow(item.t,3)var ballY=oy * math。pow((1项。t),3代入三阶贝塞尔曲线公式算出小球的坐标值自我。CTX。开始路径()自身。CTX。arc(ballX,ballY,5,0,Math .* 2,假)自我。CTX。fill()} if(ctrlDrawIndex!==ctrlnodesarr。长度){窗口。requestanimationframe(新地图。抽球。bind(self))} }最后
演示地址:这里
源码地址:欢迎星星
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。