functionsampleCurveX(t) { return ((ax * t + bx) * t + cx ) * t; }
functionsampleCurveY(t) { return ((ay * t + by) * t + cy ) * t; }
// Given an x value, find a parametric value it came from. functionsolveCurveX(x) { var t2 = x; var derivative; var x2;
// https://trac.webkit.org/browser/trunk/Source/WebCore/platform/animation // First try a few iterations of Newton's method -- normally very fast. // http://en.wikipedia.org/wiki/Newton's_method for (let i = 0; i < 8; i++) { // f(t)-x=0 x2 = sampleCurveX(t2) - x; if (Math.abs(x2) < ZERO_LIMIT) { return t2; } derivative = sampleCurveDerivativeX(t2); // == 0, failure /* istanbul ignore if */ if (Math.abs(derivative) < ZERO_LIMIT) { break; } t2 -= x2 / derivative; }
// Fall back to the bisection method for reliability. // bisection // http://en.wikipedia.org/wiki/Bisection_method var t1 = 1; /* istanbul ignore next */ var t0 = 0;
/* istanbul ignore next */ t2 = x; /* istanbul ignore next */ while (t1 > t0) { x2 = sampleCurveX(t2) - x; if (Math.abs(x2) < ZERO_LIMIT) { return t2; } if (x2 > 0) { t1 = t2; } else { t0 = t2; } t2 = (t1 + t0) / 2; }
functiongenerateCubicBezier (v, g, t){ var a = v / g; var b = t + v / g;
return [[(a / 3 + (a + b) / 3 - a) / (b - a), (a * a / 3 + a * b * 2 / 3 - a * a) / (b * b - a * a)], [(b / 3 + (a + b) / 3 - a) / (b - a), (b * b / 3 + a * b * 2 / 3 - a * a) / (b * b - a * a)]]; }
functioncreateBall() { var ball = document.createElement("div"); var t = Number(document.getElementById("t").value); var vx = Number(document.getElementById("vx").value); var vy = Number(document.getElementById("vy").value); var g = Number(document.getElementById("g").value); ball.className = "ball"; document.body.appendChild(ball) ball.style.transition = `left linear ${t}s, top cubic-bezier(${generateCubicBezier(vy, g, t)}) ${t}s`; setTimeout(function(){ ball.style.left = `${vx * t}px`; ball.style.top = `${vy * t + 0.5 * g * t * t}px`; }, 100); setTimeout(function(){ document.body.removeChild(ball); }, t * 1000); }