问题描述
好的,所以我一直在创建一个 UI 框架,并为它添加了动画。我想让用户使用cubicBeziers 来控制他们动画的计时函数,所以我决定使用p5.js 的bezierPoint()
函数。我花了几个小时让它工作,最后让它以我认为完美的方式工作......直到现在我发现它(不知何故)没有按预期工作。
当我传入一个三次贝塞尔曲线,起点/终点位于 0,1
和 1,0
,控制点位于 0.5,0.5
和 0.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