计算线性缩放的贝塞尔曲线

时间:2016-03-25 09:37:15

标签: css sass bezier easing

在循环缩放动画时,线性时序不会感觉线性,而是在开始时很慢而在结束时很快。

你将如何计算正确的曲线? 如果您需要更多信息,请在评论中提问。

在这支钢笔中,我使用手绘曲线试图解决问题,因为我显然太愚蠢而无法弄清楚逻辑。

http://codepen.io/pixelass/pen/qZjBQy

// mathematically correct curve ?
@function linear-zoom() {
  // add your code here
  $sx: 0;
  $sy: 0;
  $ex: 1;
  $ey: 1;
  $curve: ($sx, $sy, $ex, $ey);
  @return $curve;
}

zoom hack

1 个答案:

答案 0 :(得分:2)

您使用的缩放参数是2的倍数,因此当您使用线性动画 speed 时,缩放会线性增加,但 distance 会以对数方式增加。

让我们看看一些数字。首先,我们从0.5扩展到2的圆圈,因此有两个log2步骤:

t=0    => scale(0.5)
t=0.25 => scale((0.75 * 0.5 + 0.25 * 2)) = scale(0.875)
t=0.5  => scale((0.5 * 0.5 + 0.5 * 2)) = scale(1.25)
t=0.75 => scale((0.25 * 0.5 + 0.75 * 2)) = scale(1.625)
t=1    => scale(2)

因此看起来很棒,开始和结束之间的线性过渡。我们可能认为这意味着我们可以添加更多的圆圈来做同样的事情,但如果我们这样做,我们最终会得到对数行为。让我们来看看为什么:让我们说我们添加一个将0.25扩展为1的内容。

t=0    => scale(0.25)
t=0.25 => scale((0.75 * 0.25 + 0.25)) = scale(0.4375)
t=0.5  => scale((0.5 * 0.25 + 0.5)) = scale(0.625)
t=0.75 => scale((0.25 * 0.25 + 0.75)) = scale(0.8125)
t=1    => scale(1)

似乎好:在每个时间间隔,大圆的半径都是小圆圈的两倍......但是什么你想要的,因为这也意味着较小圆上的一个点只有在较大圆上的一个点移动两倍距离(1.5个单位)时才移动0.75个单位。我们看到一个圆圈开始越大,它在屏幕上移动得越快,遵循一个简单的2^t公式。

为了抵消这种情况,您需要补偿特定的对数增长,由于参数不同而独立于每个动画。获得单个Bezier曲线为所有曲线做到这一点在数学上是不可能的,但是因为人类不是完美的数学机器,你可以在像你的编码器一样的屏幕上侥幸逃脱它 - 来做它"正确"对于任何开始/结束参数集ab,您需要设置贝塞尔曲线,该曲线近似于1/(2^t)区间内的函数t=[a,b],这不是&#39}。非常有趣:我们需要使用贝塞尔曲线近似特定区间的series for 1/2^x up to order 2,然后使用给出我们的坐标作为立方宽松参数。

有两种方法可以做到这一点 - 找到一条最适合函数的Bezier曲线,从全局最小值到最大值,然后使用曲线分割找到每个子区间的参数,或者找到Bezier适合每个单独的间隔。第一个是(稍微)更容易但由于1/2^x的低阶序列近似而容易出错,第二个更好,但是相当多的工作,所以如果你想知道如何做到这一点{{3这里是一个更好的地方,可以达到真正的数学底线。

" Stackoverflow回答"大多数程序员能够使用的是为自己建立一个查找表,其中包括某些时间间隔的某些曲线"然后在它们之间使用插值来处理落在用于构建LUT的区间之间的区间:使用您所处的任何语言绘制区间,然后使用math.stackexchange.com之类的内容覆盖该图并且简单地找到"一个合适的"通过观察控制点来获得每个图。比如说,你使用的时间间隔是十分之一,而且你很乐意去。

这肯定是的数学,而且你不能编程"编程"该解决方案作为通用解决方案,但它高效的:从用户感知的角度来看,这个解决方案应该已经足够好以至于感觉顺畅了。