tic
tic

Reputation: 4199

parametrize the bounceOut ease effect in D3

In the image below, the black line describes the bounceOut function, as shown in the D3-ease documentation. Is there any way to make the bounces smaller, as in the red line?

enter image description here

Upvotes: 2

Views: 203

Answers (2)

tic
tic

Reputation: 4199

The following code, that I've found on a Custom Easing page by Mike Bostock on bl.ocks.org, makes exactly what I want, describing a parameterized bounce:

It defines the function:

function bounce(h) {
  if (!arguments.length) h = 0.25;
  var b0 = 1 - h,
      b1 = b0 * (1 - b0) + b0,
      b2 = b0 * (1 - b1) + b1,
      x0 = 2 * Math.sqrt(h),
      x1 = x0 * Math.sqrt(h),
      x2 = x1 * Math.sqrt(h),
      t0 = 1 / (1 + x0 + x1 + x2),
      t1 = t0 + t0 * x0,
      t2 = t1 + t0 * x1,
      m0 = t0 + t0 * x0 / 2,
      m1 = t1 + t0 * x1 / 2,
      m2 = t2 + t0 * x2 / 2,
      a = 1 / (t0 * t0);
  return function(t) {
    return t >= 1 ? 1
        : t < t0 ? a * t * t
        : t < t1 ? a * (t -= m0) * t + b0
        : t < t2 ? a * (t -= m1) * t + b1
        : a * (t -= m2) * t + b2;
  };
}

and then specify it as ease argument in the transition:

  d3element.transition()
      .duration(1500)
      .ease(bounce(0.2))
      ...omissis...

Upvotes: 2

Gerardo Furtado
Gerardo Furtado

Reputation: 102219

There is no native way to change that specific easing method.

However, if you look at the source code, you'll see that the bounce steps are hardcoded:

var b1 = 4 / 11,
    b2 = 6 / 11,
    b3 = 8 / 11,
    b4 = 3 / 4,
    b5 = 9 / 11,
    b6 = 10 / 11,
    b7 = 15 / 16,
    b8 = 21 / 22,
    b9 = 63 / 64,
    b0 = 1 / b1 / b1;

So, what you can easily do is creating a custom easing with a different set of values.

Just for comparison, here is the D3 easing:

d3.select("svg")
  .append("circle")
  .attr("r", 20)
  .attr("cx", 20)
  .attr("cy", 50)
  .transition()
  .ease(d3.easeBounceOut)
  .duration(2000)
  .attr("cx", 280);
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg></svg>

And here the same code, with our custom easing:

d3.select("svg")
  .append("circle")
  .attr("r", 20)
  .attr("cx", 20)
  .attr("cy", 50)
  .transition()
  .ease(customBounce)
  .duration(2000)
  .attr("cx", 280);

function customBounce(t) {
  var b1 = 50 / 64,
    b2 = 54 / 64,
    b3 = 58 / 64,
    b4 = 60 / 64,
    b5 = 62 / 64,
    b6 = 63 / 64,
    b0 = 1 / b1 / b1;
  return (t = +t) < b1 ? b0 * t * t : t < b3 ? b0 * (t -= b2) * t + b4 : b0 * (t -= b5) * t + b6;
}
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg></svg>

I didn't choose the best math according to your desired outcome, that's just a general explanation, so you can do it by yourself.

Upvotes: 2

Related Questions