1
votes

I have the ease cubic-bezier function: cubic-bezier(.25,.1,.25,1) (http://cubic-bezier.com/#.25,.1,.25,1)

I want the opposite of this. Here is graphic representation of what I'm trying to accomplish:

The graph on left is what I have, and the function for the graph on the right is what I'm trying to achieve.

Image

2
What do you mean with "opposite"? (this is not as silly a question as it sounds: bezier curves have several aspects, all of which could have an 'opposite' at any or all points).Mike 'Pomax' Kamermans
Oh what I mean is, i want to create a css transition that follows the curve in reverse. Curve should be exactly the same, its just that thime 0 is now at other end.Noitidart
CSS cubic bezier curves are defined only by two middle control points, and the first vertex is fixed at (0,0) and the last one at (1,1). developer.mozilla.org/en-US/docs/Web/CSS/timing-function By that definition, you can't follow the curve in reverse, can you?hkrish
I totally know what you mean man. I just need to make the same path from 1,1 to 0,0 be the opposite of what it was.Noitidart
Ah, that's a straight up rotation about (0.5,0.5). Bezier curves are invariant under linear transforms, so you can literally just rotate all the points. I'll write up an answer with the math for that.Mike 'Pomax' Kamermans

2 Answers

4
votes

If you want to do a rotation as in your updated answer, all we have to do is... well, that. Rotate around (0.5,0.5) by a 180 degree, or π radians, angle. Let's assume we have a curve encoded as an array c with four point objects { x:..., y... }, then we can effect this rotation as:

c = [ {x:...,y:...}, ..., ..., ...];

function halfUnitTurn(v) {
  // Note: it's actually 0.5 + ((v.x-0.5)*cos(pi) - (v.x-0.5)*sin(pi)),
  // (and x*sin + y*cos for the y:... part) but: cos(pi) is just -1, and
  // sin(pi) is 0, so things REALLY simplify!
  return {
    x: 0.5 - (v.x-0.5),
    y: 0.5 - (v.y-0.5)
  };
}

var rotated = c.map(function(p) { return halfUnitTurn(p); });

And as demonstrator code: http://jsfiddle.net/mokg77fq/

2
votes

Here is Mike's awesome code put into a reusable function:

function reverseCssCubicBezier(cubicBezier) {
    var maxX = Math.max(cubicBezier[0].x, cubicBezier[1].x, cubicBezier[2].x, cubicBezier[3].x);
    var maxY = Math.max(cubicBezier[0].y, cubicBezier[1].y, cubicBezier[2].y, cubicBezier[3].y);
    var halfUnitTurn = function(v) {
        var tx = maxX/2, ty = maxY/2;
        return { x: tx - (v.x-tx), y: ty - (v.y-ty) };
    };
    var revd = cubicBezier.map(halfUnitTurn);
    return revd.reverse();
}

And this is how to use it:

var ease = [{x:0,y:0}, {x:.25,y:.1}, {x:.25,y:1}, {x:1,y:1}]; //cubic-bezier(.25, .1, .25, 1)
var ease_reversed = reverseCssCubicBezier(ease);
var ease_css_string = 'cubic_bezier(' + [ease[1].x, ease[1].y, ease[2].x, ease[2].y].join(', ') + ')';
var ease_reversed_css_string = 'cubic_bezier(' + [ease_reversed[1].x, ease_reversed[1].y, ease_reversed[2].x, ease_reversed[2].y].join(', ') + ')';

This returns:

ease: [{x:0, y:0}, {x:0.25, y:0.1}, {x:0.25, y:1}, {x:1, y:1}]
ease-reversed: [{x:0, y:0}, {x:0.75, y:0}, {x:0.75, y:0.9}, {x:1, y:1}]

ease: cubic_bezier(0.25, 0.1, 0.25, 1)
ease-reversed: cubic_bezier(0.75, 0, 0.75, 0.9)

Graphically we see its perfect overlap, i shifted the green one to left a little bit to show its perfectly overlapping.

Thanks Mike!