为什么 p5.js bezierPoint() 函数在给定线性三次贝塞尔曲线时返回非线性值?

问题描述 投票:0回答:2

好吧,我一直在创建一个 UI 框架并向其中添加动画。我想让用户使用cubicBeziers控制动画的计时功能,所以我决定使用p5.js的

bezierPoint()
函数。我花了几个小时让它工作,终于让它以我认为完美的方式工作......直到现在我发现它(不知何故)没有按预期工作。

当我传入一个起点/终点位于

0,1
1,0
且控制点位于
0.5,0.5
0.5,0.5
的三次贝塞尔曲线(这是线性三次贝塞尔曲线)时,我会得到一个 eased 动画,无需任何操作。原因...这应该会产生线性动画(可以在here进行演示),但不知何故它不是。

所以我进一步研究它只是为了证明我不仅仅是看到东西,而且果然,它实际上给出了非线性数字。我写了这个小代码片段:

<script src = "https://cdn.jsdelivr.net/npm/[email protected]/lib/p5.min.js"></script>

<script>
    function setup(){
        createCanvas(100,100);
    }
    
    function draw(){
        background(255,255,0);
                
        noFill();
        stroke(0,0,0);
        strokeWeight(3);
        bezier(0,100,50,50,50,50,100,0);

        ellipse(bezierPoint(0,50,50,100,frameCount / 100),bezierPoint(100,50,50,0,frameCount / 100),5,5);
        
        ellipse(50,bezierPoint(100,50,50,0,frameCount / 100),5,5);
        ellipse(60,100 - frameCount,5,5);
    }
</script>

您可以非常清楚地看到,与线性速度(右侧的点)相比,

bezierPoint()
(左侧的点)后面的点以非线性速度移动

为什么会出现这种情况?


只是为了方便起见我将其包含在这里。这是 p5.js 的

bezierPoint()
函数:

function bezierPoint(e,t,r,i,n){
    var a = 1 - n;
    return(Math.pow(a,3) * e + 3 * Math.pow(a,2) * n * t + 3 * a * Math.pow(n,2) * r + Math.pow(n,3) * i);
}
javascript p5.js bezier
2个回答
0
投票

当三次贝塞尔曲线的 4 个控制极点共线时,贝塞尔曲线确实会看起来“线性”。但这并不意味着这条贝塞尔曲线与从 P0 到 P3 的直线完全相同。直线的一阶导数是常数,但线性贝塞尔曲线的一阶导数不是常数(一般情况下)。

要获得“真正的”线性三次贝塞尔曲线,需要将两个中间控制点 P1 和 P2 放置在

P1 = P0 + (P3-P0)/3
P2 = P0 + 2*(P3-P0)/3

0
投票

好吧,经过继续研究,这似乎是预期的行为不知何故。

我发现了这个问题:使用三次贝塞尔函数自定义动画

其中指出“我在一个问题上看到回答者建议简单地消除 x 并将函数定义为 y 针对 t。但是,这会给出非常不准确的结果,因为从 0.0 到 1.0 的线性贝塞尔曲线不会线性动画。 ”

这让我意识到我在这里看到的是某种预期的行为。我就是无法用我的大脑来解决它。

© www.soinside.com 2019 - 2024. All rights reserved.