How d3 can calculate exact animation delay for a given ease

I will try to elaborate on my question with an notebook. Please refresh the browser when you are on the notebook to trigger the animation and run cell.

In this, I am trying to animate both the Y and X-Axis stroke-dasharray so that it looks like both the axis are getting drawn.

Each of these axes also consists of .tick>.line and .tick>.text class which I want to show only when the animation reaches that particular .tick class. I want to assign initial opacity as 0 and when the animation reaches that point I want the opacity to become 1 for that particular class at that exact point.

In order to be able to do that, I need to know for a given d3.ease how long does it take for a particular animation to reach from point A to point B. For example, horizontalDistnace returns the following and I want to know for a given ease d3.easeQuadIn and for a given total time (animation -duration) 5000ms, how long does it take a path to reach to each of the following distance starting from x=0.

[
    0.5,
    53.22727272727273,
    105.95454545454545,
    158.68181818181816,
    211.4090909090909,
    264.1363636363636,
    316.8636363636363,
    369.59090909090907,
    422.3181818181818,
    475.04545454545456,
    527.7727272727273,
    580.5
]

If d3 used CSS bezier-curve values cubic-bezier(P1.x, P1.y, P2.x, P2.y), I know how to calculate the exact animation delay for a given element (i.e. how long does it take an animation to reach to point A from point B for given cubic-bezier value). Please take a look below where I have applied Rotation on the vertical lines and not until the horizontal line reaches each of them.

Since d3 ease does not use cubic-bezier values, I was wondering is there a way to calculate, for a given ease what would be the t for a given d?

What you are looking for is an inverse function for d3.easeQuadIn?

Given that easeQuadIn is computed with t => t * t (d3-ease/quad.js at main · d3/d3-ease · GitHub), the inverse should be t => Math.sqrt(t).

However this would not be a generic answer (some easing functions are just not going to be invertible). An alternative approach is to compare the current length with the ticks positions, and trigger something each time a threshold is reached. See Animate axis / Fil / Observable

1 Like

I took a different approach. d3 ease are based on Penner’s equation, which provides an equation to calculate p as a function of t.

p=f(t), it has 4 paramaeters. For linear easing it is, p= c*(t/d)+b where c = total change in postion, t = elapsed time in percentage, d=total duration (1), b = beginning position.

From this equation, I solved for t.

For easeInQuad/d3.easeQuadIn, the equation is