全国服务热线:4008-888-888

技术知识

canvas进阶之贝塞尔公式推导与物件追随繁杂曲线

写在最前

在以前的这篇文章内容中大家提到了针对贝塞尔公式的应用。本次共享1下怎样推导贝塞尔公式和附1个简易的🌰即小球追随曲线图运动轨迹健身运动。

实际效果预览

demo详细地址

针对怎样绘图持续的贝塞尔曲线图能够参考这篇文章内容:根据canvas应用贝塞尔曲线图光滑拟合折直线

在本例中转化成的曲线图由以上文章内容中的源代码出示。

贝塞尔曲线图公式推导

上面这张图是贝塞尔曲线图的详细公式,看起来1脸懵逼=。=,由于这是N阶的推导公式,本次大家以12阶贝塞尔公式的推导来了解1下这个推导公式的来历。先看来下在网上流传已久的几张贝塞尔动图:

在这3张图中最关键的一部分是大家必须了解自变量t。t的赋值范畴是0⑴。从上面的gif中还可以看出来好像曲线图的绘图全过程便是t从0到1的全过程。嗯实际上便是这样的。t的真正含意是甚么呢?

在p0p1、p1p2、p2p3这些的起始点到操纵点再到终点站的连线中,每段连线都被切分变成两一部分(细心看动图中的黑色、翠绿色、蓝色圆点),各段连线中两一部分的比值全是同样的,比值范畴是0到1,而这个比值便是t

看来下面的1阶贝塞尔曲线图示用意:

pt是p0p1上的随意1点,p0pt / ptp1 = t。从而大家能够引出下面的推导

此时t为時间,v为速率。大家能够看作从p0到p1的间距等于固定不动速率乘以固定不动時间

故到p上某1点的時间为固定不动的速率乘以某个時间值。另外固定不动的速率早已早已能够表明为上面的推导公式。此时等式右侧就产生了t(0,1) / t;即非常于某个時间值 / 固定不动時间值,即造成了大家1刚开始所强调的自变量t,其赋值范畴为[0,1]。从而下面的等式也就较为好了解了。

至此1阶贝塞尔曲线图大家早已推到了出来,在其中自变量为起始点、终点站与比值t。

那末2阶公式怎样从1阶过度过去呢?

看来下面这张图:

在其中Pp(t)的历经相对路径便是大家所求的2阶贝塞尔曲线图,那末实际上大家还可以将其从1阶开展演化:

大家先将pa、pb两个点所连直线作为1阶曲线图,以后再由两边1阶曲线图各自表明pa、pb,最终就获得了大家的2阶曲线图公式。细心观查就可以发现这和大家最开始的详细公式是同样的:

在其中n挑选不一样标值时便可以得出不一样阶的曲线图公式。另外从上面的推导全过程还可以了解,无论是几阶曲线图,大家都可以以彻底由1阶来表明,而这个“表明”的全过程便是大家在上面看到的产生动漫中那些輔助线。故能够体会下作者自身写的曲线图产生动漫中的实际效果,每段輔助线均由1阶曲线图产生:

有关详细地址

物件追随繁杂曲线图运动轨迹健身运动

当大家了解曲线图的公式有何而来以后,怎样让小球沿着曲线图健身运动就很好了解了。大家转化成的每段曲线图全是能够用公式表明出来的,也正因这般大家便可以获得每一个t值时的曲线图座标点。从而了解物件的绘图座标。

//关键逻辑性
LinearGradient.prototype.drawBall = function() {
    var self = this
    var item = ctrlNodesArr[ctrlDrawIndex] 
    //储存了各段曲线图的操纵点
    //各段曲线图均为3阶贝塞尔,故下面测算x,y值代入到了3阶公式中
    var ctrlAx = item.cAx,//各个操纵点
        ctrlAy = item.cAy,
        ctrlBx = item.cBx,
        ctrlBy = item.cBy,
    ...
    if(item.t > 1) {
        ctrlDrawIndex++ //当1段曲线图的t>1表明曲线图早已走到头
    }else {
        self.ctx.clearRect(0, 0, self.width, self.height)
        item.t += 0.05
        var ballX = ox * Math.pow((1 - item.t), 3) + 3 * ctrlAx * item.t * Math.pow((1 - item.t), 2) + 3 * ctrlBx * Math.pow(item.t, 2) * (1 - item.t) + x * Math.pow(item.t, 3)
        var ballY = oy * Math.pow((1 - item.t), 3) + 3 * ctrlAy * item.t * Math.pow((1 - item.t), 2) + 3 * ctrlBy * Math.pow(item.t, 2) * (1 - item.t) + y * Math.pow(item.t, 3)
        //代入3阶贝塞尔曲线图公式算出小球的座标值
        self.ctx.beginPath()
        self.ctx.arc(ballX, ballY, 5, 0, Math.PI * 2, false)
        self.ctx.fill()
    }
    if(ctrlDrawIndex !== ctrlNodesArr.length) {
        window.requestAnimationFrame(newMap.drawBall.bind(self))
    }
}

最终

demo详细地址:这里✨✨

源代码详细地址:欢迎star

以上便是本文的所有內容,期待对大伙儿的学习培训有一定的协助,也期待大伙儿多多适用脚本制作之家。



在线客服

关闭

客户服务热线
4008-888-888


点击这里给我发消息 在线客服

点击这里给我发消息 在线客服