6

I'm having trouble figuring out this simple math problem. I have spent over two hours reading through various related answers on SO and Google, but it seems my high school math knowledge is gone.

On the page I have an element, that, once it passes a threshold, gets scaled down, the closer it gets to the edge of the containing element. Right now, it scales in a linear fashion. I calculate the distance to the container's edge, compare it to the threshold value (where the scale is 100%) and calculate a percentage from that, that is used to actually scale the Element (via CSS transform).

What I would like, is for the scaling to start slowly for about the first 60-80% and then ramp up considerably.

To me it seems I need some sort of inverse exponential or logarithmic function to do this, but I can't figure out exactly how to implement this. Ideally, the function would return 0.0 for x = threshold and 1.0 for x = 0 (where x would be the element's current position/percentage).

Any help is appreciated. I think this is probably trivial, but I cannot wrap my head around it.

oelna
  • 2,210
  • 3
  • 22
  • 40
  • Can you use a library ? jQuery has an "animate" function where you can specify the type of interpolation you want. – Cyril Duchon-Doris May 02 '15 at 21:55
  • 1
    In theory, yes, but I believe this is not feasable. The calculation happens inside a drag event and is refreshed with every mouse move. That's why I phrased the question in a more abstract math way. – oelna May 02 '15 at 21:59
  • Did you check [jQuery UI's draggable](http://jqueryui.com/draggable/#events) ? – Cyril Duchon-Doris May 02 '15 at 22:03

5 Answers5

10

Here's two you could try:

(cos(pi*x) + 1) / 2

Plot on Wolfram Alpha

1 - x^2

Plot on Wolfram Alpha

Depending on if you want them to ease out or be steep at the threshold. These are normalized to (0,1), but you can easily scale them to whatever interval by dividing x by your threshold.

cfh
  • 4,576
  • 1
  • 24
  • 34
5

Here you go:

function easeInOutQuad(t, b, c, d) {
    t /= d/2;
    if (t < 1) return c/2*t*t + b;
    t--;
    return -c/2 * (t*(t-2) - 1) + b;
}

where

  • t is current time
  • b is start value
  • c is change in value
  • d is duration

it's all supplied from this great list of easing equations: http://gizma.com/easing/

Marc
  • 13,011
  • 11
  • 78
  • 98
Emil Ingerslev
  • 4,645
  • 2
  • 24
  • 18
3

If you want a super simple ease-in-out cubic, I think this one does the job

function easeInOut(t){
  return t > 0.5 ? 4*Math.pow((t-1),3)+1 : 4*Math.pow(t,3);
}

It basically uses the saddle point inx^3 from 0 to 0.5, then takes another x^3 curve and translates it to be the end. t needs to be in the domain [0,1]

http://plnkr.co/edit/QiY8RR9KPCvoA8ZXVtPY?p=preview

user1506145
  • 5,176
  • 11
  • 46
  • 75
1

Below you see the code of this easing function written in TypeScript.

function easeInOutQuad(x: number): number {
      return x < 0.5 ? 2 * x * x : 1 - pow(-2 * x + 2, 2) / 2;
    }
0

Bouncing on my comment, you can use jQuery's animate() like this (example extracted from the doc)

$( "#clickme" ).click(function() {
  $( "#book" ).animate({
    width: "toggle",
    height: "toggle"
  }, {
    duration: 5000,
    specialEasing: {
      width: "linear",
      height: "easeOutBounce"
    },
    complete: function() {
      $( this ).after( "<div>Animation complete.</div>" );
    }
  });
});

List of all easing functions.

Cyril Duchon-Doris
  • 12,964
  • 9
  • 77
  • 164