admin管理员组文章数量:1208155
In CSS3 transitions, you can specify a timing function as 'cubic-bezier:(0.25, 0.3, 0.8, 1.0)' In that string, you are only specifying the XY for points P1 and P2 along the curve, as P0 and P3 are always (0.0, 0.0), and (1.0, 1.0) respectively.
According to Apple's site: x [is] expressed as a fraction of the overall duration and y expressed as a fraction of the overall change
My question is how can this be mapped back to a traditional 1 dimensional T value in javascript?
--
From Apple docs on animating with transitions
In CSS3 transitions, you can specify a timing function as 'cubic-bezier:(0.25, 0.3, 0.8, 1.0)' In that string, you are only specifying the XY for points P1 and P2 along the curve, as P0 and P3 are always (0.0, 0.0), and (1.0, 1.0) respectively.
According to Apple's site: x [is] expressed as a fraction of the overall duration and y expressed as a fraction of the overall change
My question is how can this be mapped back to a traditional 1 dimensional T value in javascript?
--
From Apple docs on animating with transitions
3 Answers
Reset to default 22Browsing through webkit-source a bit, the following code will give the correct T value for the implicit curve used in CSS3 transitions:
Visual demo (codepen.io)
Hope this helps someone!
function loop(){
var t = (now - animationStartTime) / ( animationDuration*1000 );
var curve = new UnitBezier(Bx, By, Cx, Cy);
var t1 = curve.solve(t, UnitBezier.prototype.epsilon);
var s1 = 1.0-t1;
// Lerp using solved T
var finalPosition.x = (startPosition.x * s1) + (endPosition.x * t1);
var finalPosition.y = (startPosition.y * s1) + (endPosition.y * t1);
}
/**
* Solver for cubic bezier curve with implicit control points at (0,0) and (1.0, 1.0)
*/
function UnitBezier(p1x, p1y, p2x, p2y) {
// pre-calculate the polynomial coefficients
// First and last control points are implied to be (0,0) and (1.0, 1.0)
this.cx = 3.0 * p1x;
this.bx = 3.0 * (p2x - p1x) - this.cx;
this.ax = 1.0 - this.cx -this.bx;
this.cy = 3.0 * p1y;
this.by = 3.0 * (p2y - p1y) - this.cy;
this.ay = 1.0 - this.cy - this.by;
}
UnitBezier.prototype.epsilon = 1e-6; // Precision
UnitBezier.prototype.sampleCurveX = function(t) {
return ((this.ax * t + this.bx) * t + this.cx) * t;
}
UnitBezier.prototype.sampleCurveY = function (t) {
return ((this.ay * t + this.by) * t + this.cy) * t;
}
UnitBezier.prototype.sampleCurveDerivativeX = function (t) {
return (3.0 * this.ax * t + 2.0 * this.bx) * t + this.cx;
}
UnitBezier.prototype.solveCurveX = function (x, epsilon) {
var t0;
var t1;
var t2;
var x2;
var d2;
var i;
// First try a few iterations of Newton's method -- normally very fast.
for (t2 = x, i = 0; i < 8; i++) {
x2 = this.sampleCurveX(t2) - x;
if (Math.abs (x2) < epsilon)
return t2;
d2 = this.sampleCurveDerivativeX(t2);
if (Math.abs(d2) < epsilon)
break;
t2 = t2 - x2 / d2;
}
// No solution found - use bi-section
t0 = 0.0;
t1 = 1.0;
t2 = x;
if (t2 < t0) return t0;
if (t2 > t1) return t1;
while (t0 < t1) {
x2 = this.sampleCurveX(t2);
if (Math.abs(x2 - x) < epsilon)
return t2;
if (x > x2) t0 = t2;
else t1 = t2;
t2 = (t1 - t0) * .5 + t0;
}
// Give up
return t2;
}
// Find new T as a function of Y along curve X
UnitBezier.prototype.solve = function (x, epsilon) {
return this.sampleCurveY( this.solveCurveX(x, epsilon) );
}
You want to find the [0,1] value for any time value t [0,1]? There's a well-defined equation for a cubic bezier curve. Wikipedia page: http://en.wikipedia.org/wiki/B%C3%A9zier_curve#Cubic_B.C3.A9zier_curves
So I don't have to type out their (probably LaTeX-formatted) formula, I copy-pasted the same formula from http://local.wasp.uwa.edu.au/~pbourke/geometry/bezier/index2.html . This also has a C implementation which, on a quick read-through, should be easy to port to javascript:
B(u) = P0 * ( 1 - u )3 + P1 * 3 * u * ( 1 - u )2 + P2 * 3 * u2 * ( 1 - u ) + P3 * u3
What he's calling mu on that page is your time variable t.
Edit: If you don't want to do the math it looks like someone already wrote a small utility library in javascript to do basic bezier curve math: https://github.com/sporritt/jsBezier . pointOnCurve(curve, location) looks like just what you're asking for.
I have try and search a lot of time and forms and definetly i have reached one simple and fast. The trick is get the cubic bezier function in this form: P(u) = u^3(c0 + 3c1 -3c2 +c3) + u^2(3c0 -6c1 +3c2) + u(-3c0 +3c1) + c0 where ci are the control points. The other part is search y from x with a binary search.
static public class CubicBezier {
private BezierCubic bezier = new BezierCubic();
public CubicBezier(float x1, float y1, float x2, float y2) {
bezier.set(new Vector3(0,0,0), new Vector3(x1,y1,0), new Vector3(x2,y2,0), new Vector3(1,1,1));
}
public float get(float t) {
float l=0, u=1, s=(u+l)*0.5f;
float x = bezier.getValueX(s);
while (Math.abs(t-x) > 0.0001f) {
if (t > x) { l = s; }
else { u = s; }
s = (u+l)*0.5f;
x = bezier.getValueX(s);
}
return bezier.getValueY(s);
}
};
public class BezierCubic {
private float[][] cpoints = new float[4][3];
private float[][] polinom = new float[4][3];
public BezierCubic() {}
public void set(Vector3 c0, Vector3 c1, Vector3 c2, Vector3 c3) {
setPoint(0, c0);
setPoint(1, c1);
setPoint(2, c2);
setPoint(3, c3);
generate();
}
public float getValueX(float u) {
return getValue(0, u);
}
public float getValueY(float u) {
return getValue(1, u);
}
public float getValueZ(float u) {
return getValue(2, u);
}
private float getValue(int i, float u) {
return ((polinom[0][i]*u + polinom[1][i])*u + polinom[2][i])*u + polinom[3][i];
}
private void generate() {
for (int i=0; i<3; i++) {
float c0 = cpoints[0][i], c1 = cpoints[1][i], c2 = cpoints[2][i], c3 = cpoints[3][i];
polinom[0][i] = c0 + 3*(c1 - c2) + c3;
polinom[1][i] = 3*(c0 - 2*c1 + c2);
polinom[2][i] = 3*(-c0 + c1);
polinom[3][i] = c0;
}
}
private void setPoint(int i, Vector3 v) {
cpoints[i][0] = v.x;
cpoints[i][1] = v.y;
cpoints[i][2] = v.z;
}
}
本文标签: javascriptRecreating CSS3 transitions CubicBezier curveStack Overflow
版权声明:本文标题:javascript - Recreating CSS3 transitions Cubic-Bezier curve - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1738672519a2106079.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
length
is a function of thet
value. Not really sure how you'd go about getting that though. – Wex Commented Jul 27, 2012 at 23:09