(function(ionic) { var bezierCoord = function (x,y) { if(!x) var x=0; if(!y) var y=0; return {x: x, y: y}; } function B1(t) { return t*t*t } function B2(t) { return 3*t*t*(1-t) } function B3(t) { return 3*t*(1-t)*(1-t) } function B4(t) { return (1-t)*(1-t)*(1-t) } ionic.Animator = { // Quadratic bezier solver getQuadraticBezier: function(percent,C1,C2,C3,C4) { var pos = new bezierCoord(); pos.x = C1.x*B1(percent) + C2.x*B2(percent) + C3.x*B3(percent) + C4.x*B4(percent); pos.y = C1.y*B1(percent) + C2.y*B2(percent) + C3.y*B3(percent) + C4.y*B4(percent); return pos; }, // Cubic bezier solver from https://github.com/arian/cubic-bezier (MIT) getCubicBezier: function(x1, y1, x2, y2, duration) { // Precision epsilon = (1000 / 60 / duration) / 4; var curveX = function(t){ var v = 1 - t; return 3 * v * v * t * x1 + 3 * v * t * t * x2 + t * t * t; }; var curveY = function(t){ var v = 1 - t; return 3 * v * v * t * y1 + 3 * v * t * t * y2 + t * t * t; }; var derivativeCurveX = function(t){ var v = 1 - t; return 3 * (2 * (t - 1) * t + v * v) * x1 + 3 * (- t * t * t + 2 * v * t) * x2; }; return function(t) { var x = t, t0, t1, t2, x2, d2, i; // First try a few iterations of Newton's method -- normally very fast. for (t2 = x, i = 0; i < 8; i++){ x2 = curveX(t2) - x; if (Math.abs(x2) < epsilon) return curveY(t2); d2 = derivativeCurveX(t2); if (Math.abs(d2) < 1e-6) break; t2 = t2 - x2 / d2; } t0 = 0, t1 = 1, t2 = x; if (t2 < t0) return curveY(t0); if (t2 > t1) return curveY(t1); // Fallback to the bisection method for reliability. while (t0 < t1){ x2 = curveX(t2); if (Math.abs(x2 - x) < epsilon) return curveY(t2); if (x > x2) t0 = t2; else t1 = t2; t2 = (t1 - t0) * .5 + t0; } // Failure return curveY(t2); }; }, animate: function(element, className, fn) { return { leave: function() { var endFunc = function() { console.log('Animation finished for element', element); element.classList.remove('leave'); element.classList.remove('leave-active'); element.removeEventListener('webkitTransitionEnd', endFunc); element.removeEventListener('transitionEnd', endFunc); }; element.addEventListener('webkitTransitionEnd', endFunc); element.addEventListener('transitionEnd', endFunc); element.classList.add('leave'); element.classList.add('leave-active'); return this; }, enter: function() { var endFunc = function() { console.log('Animation finished for element', element); element.classList.remove('enter'); element.classList.remove('enter-active'); element.removeEventListener('webkitTransitionEnd', endFunc); element.removeEventListener('transitionEnd', endFunc); }; element.addEventListener('webkitTransitionEnd', endFunc); element.addEventListener('transitionEnd', endFunc); element.classList.add('enter'); element.classList.add('enter-active'); return this; } }; } }; })(ionic);