Does d3.js have reverse ease functions?

2020-03-24 07:58发布

问题:

With d3.js we can achieve eased time out of normalized time t, typically in the range [0,1]

For example:

d3.easeCubic(0.25) = 0.0625

How can we reverse that, how can we find x given known y ?

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

The answer here is cubic root, but still.

The problem is in reusability, ease function can change to d3.easeExpIn, or `d3.easeCircleOut, or any other, do you need to invent reverse functions on your own, or are they hidden anywhere ?

回答1:

Firstly, your math is wrong. d3.easeCubic(0.25) will give you 0.0625:

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

Now, back to your question:

How can we reverse that, how can we find x given known y?

There is no native solution, but we can create our own function to find X given a known Y. The problem, of course, is that we have to invert the math for each specific easing... But, since you asked about d3.easeCubic, which is the same of d3.easeCubicInOut, let's try to create an inverted function for that particular easing.

First step, let's have a look at the source code:

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

You can easily see that this is the correct function, giving us the same value as the first snippet:

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

console.log(cubicInOut(0.25))

Now, let's try to invert it.

The math here is somehow complicated, but for values less than 1, here is the function:

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

And here is the demo. We pass 0.0625 to the function, and it returns 0.25:

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

console.log(inverseEaseCubic(0.0625))

If you want to deal with numbers bigger than 1, this is the complete function:

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

PS: In his comment, @altocumulus just reminded us that, sometimes, it's even impossible to find the value. Here is a very simple example. Suppose this function:

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

Now imagine that, when called with an unknown argument, the function returned 4. What's the argument? Can we find out? Impossible to determine, because second degree equations, like this one, have 2 roots:

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


回答2:

I used the @Gerardo Furtado answer but the inverse function didn't work well so I wrote another

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);



标签: d3.js