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

问题描述

好的,所以我一直在创建一个 UI 框架,并为它添加了动画。我想让用户使用cubicBeziers 来控制他们动画的计时函数,所以我决定使用p5.js 的bezierPoint() 函数。我花了几个小时让它工作,最后让它以我认为完美的方式工作......直到现在我发现它(不知何故)没有按预期工作。

当我传入一个三次贝塞尔曲线,起点/终点位于 0,11,0,控制点位于 0.5,0.50.5,0.5(这是一个线性三次贝塞尔曲线) ,我无缘无故地得到一个缓动动画...这应该产生一个线性动画(可以演示here)但不知何故它不是。

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

<script src = "https://cdn.jsdelivr.net/npm/p5@1.3.1/lib/p5.min.js"></script>

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

        ellipse(bezierPoint(0,frameCount / 100),bezierPoint(100,5,5);
        
        ellipse(50,5);
        ellipse(60,100 - frameCount,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);
}

解决方法

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

我发现了这个问题:Custom animation using cubic Bezier function

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

这让我明白,我在这里看到的是某种预期的行为......我就是无法理解它。

采用线性曲线和动画值t 线性如何给出非线性结果?!我的代码中没有任何内容是非线性的,但不知何故我得到了非线性动画。这对我来说真的完全没有意义,但现在我知道这是预期的行为,我想我可以期望不会收到我正在寻找的答案。

,

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

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

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