d3.js是否具有反向缓动功能?

时间:2017-01-10 12:58:16

标签: d3.js

使用d3.js,我们可以在标准化时间t之外缩短时间,通常在[0,1]范围内

例如:

d3.easeCubic(0.25) = 0.0625

我们如何扭转这一局面,我们怎样才能找到已知y的x?

d3.easeCubic(X) = 0.0625,
X ???

这里的答案是立方根,但仍然。

问题在于可重用性,缓和功能可以改为d3.easeExpIn,或者`d3.easeCircleOut,还是其他任何一种,你需要自己创建反向函数,还是隐藏在任何地方?

2 个答案:

答案 0 :(得分:4)

首先,你的数学错了。 d3.easeCubic(0.25)将为您提供0.0625

var easy = d3.easeCubic(0.25);
console.log(easy);
<script src="https://d3js.org/d3.v4.min.js"></script>

现在,回到你的问题:

  

我们如何扭转这一局面,我们怎样才能找到已知y的x?

没有本机解决方案,但是我们可以创建自己的函数来找到已知Y的X.问题当然是我们必须为每个特定的缓动转换数学...但是,因为你问大约d3.easeCubic,与d3.easeCubicInOut相同,让我们尝试为该特定宽松创建一个倒置函数。

首先,让我们看一下源代码:

export function cubicInOut(t) {
    return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2;
}

您可以很容易地看到这是正确的功能,为我们提供与第一个代码段相同的值:

function cubicInOut(t) {
    return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2;
}

console.log(cubicInOut(0.25))

现在,我们试着颠倒它。

这里的数学有点复杂,但对于小于1的值,这里是函数:

function inverseEaseCubic(t){
    return Math.cbrt(t * 2) / 2;
}

这是演示。我们将0.0625传递给函数,然后返回0.25

function inverseEaseCubic(t){
    return Math.cbrt(t * 2) / 2;
}

console.log(inverseEaseCubic(0.0625))

如果你想处理大于1的数字,这就是完整的功能:

function InverseEaseCubic(t){
    return t <= 1 ? Math.cbrt(t * 2) / 2 : (Math.cbrt(2 * t - 2) + 2) / 2;
}

PS:his comment中,@ altocumulus只是提醒我们,有时甚至不可能来找到价值。这是一个非常简单的例子。假设这个功能:

function exponentiation(a){
    return a*a;
}

现在想象一下,当使用未知参数调用时,函数返回4。争论是什么?我们能找到吗?无法确定,因为像这样的二度方程有两个根:

console.log(exponentiation(2))//returns 4
console.log(exponentiation(-2))//also returns 4 

答案 1 :(得分:0)

我使用了@Gerardo Furtado的答案,但是反函数不能很好地工作,所以我写了另一个

function cubicInOut(t) {
  return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2;
}
function inverseEaseCubic(x) {
  return x < .5 ? Math.cbrt(x / 4) : (2 - Math.cbrt(2 - 2 * x)) / 2;
}
  
console.log(inverseEaseCubic(cubicInOut(1)) === 1);
console.log(inverseEaseCubic(cubicInOut(0.6)) === 0.6);
console.log(inverseEaseCubic(cubicInOut(0.4)) === 0.4);
console.log(inverseEaseCubic(cubicInOut(0.1)) === 0.1);
console.log(inverseEaseCubic(cubicInOut(0)) === 0);