mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-11-07 06:57:02 +08:00
Emulates the CSS cubic-bezier function to interpolate transition values to trigger intermediate scroll events.
116 lines
3.4 KiB
JavaScript
116 lines
3.4 KiB
JavaScript
(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);
|