2012-07-27 17 views
5

CSS3 संक्रमण में, आप 'क्यूबिक-बेज़ीयर: (0.25, 0.3, 0.8, 1.0)' के रूप में एक समय कार्य निर्दिष्ट कर सकते हैं, उस स्ट्रिंग में, आप केवल अंक P1 के लिए XY निर्दिष्ट कर रहे हैं और वक्र के साथ पी 2, पी 0 और पी 3 हमेशा क्रमशः (0.0, 0.0), और (1.0, 1.0) हैं।CSS3 संक्रमणों को दोबारा बनाना क्यूबिक-बेजियर वक्र

एप्पल साइट के अनुसार: एक्स [है] समग्र अवधि का एक अंश के रूप में व्यक्त और y समग्र परिवर्तन का एक अंश के रूप में व्यक्त

मेरे सवाल यह है कि इस एक पारंपरिक 1 आयामी करने के लिए वापस मैप किया जा सकता है जावास्क्रिप्ट में टी मान?

-

From Apple docs on animating with transitions
enter image description here

+0

'' length' t' मूल्य के एक समारोह है। वास्तव में यह सुनिश्चित नहीं है कि आप इसे प्राप्त करने के बारे में कैसे जाएंगे। – Wex

उत्तर

16

वेबकिट-स्रोत के माध्यम से ब्राउज़िंग एक सा है, तो निम्न कोड निहित CSS3 के संक्रमण में इस्तेमाल की अवस्था के लिए सही टी मूल्य दे देंगे:

Visual demo (codepen.io)

आशा इस कोई मदद करता है!

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)); 
} 
0

आप [0,1] किसी भी समय मूल्य टी [0,1] के लिए मूल्य को खोजने के लिए करना चाहते हैं? एक घन बेजियर वक्र के लिए एक अच्छी तरह से परिभाषित समीकरण है। विकिपीडिया पृष्ठ: http://en.wikipedia.org/wiki/B%C3%A9zier_curve#Cubic_B.C3.A9zier_curves

इसलिए मुझे अपने (शायद लाटेक्स-स्वरूपित) फॉर्मूला को टाइप करने की आवश्यकता नहीं है, मैंने http://local.wasp.uwa.edu.au/~pbourke/geometry/bezier/index2.html से उसी सूत्र को कॉपी-पेस्ट किया है।

B(u) = P0 * (1 - u)3 + P1 * 3 * u * (1 - u)2 + P2 * 3 * u2 * (1 - u) + P3 * u3

क्या वह उस पृष्ठ पर म्यू कॉल कर रहा है अपना समय चर टी है: यह भी एक सी कार्यान्वयन जो, एक त्वरित पढ़ने के माध्यम से पर, जावास्क्रिप्ट को बंदरगाह के लिए आसान होना चाहिए है।

संपादित करें: यदि आप गणित नहीं करना चाहते हैं तो ऐसा लगता है कि मूल बेजियर वक्र गणित करने के लिए जावास्क्रिप्ट में किसी ने पहले से ही एक छोटी उपयोगिता लाइब्रेरी लिखी है: https://github.com/sporritt/jsBezier। pointOnCurve (वक्र, स्थान) बस वही दिखता है जो आप पूछ रहे हैं।

+0

यह वक्र के साथ बिंदु पी देता है, लेकिन ऑब्जेक्ट को स्थानांतरित करने के लिए उस स्थिति को अंतिम स्थिति में अनुवाद करने का तरीका नहीं है। (मैं वस्तु को वक्र के साथ नहीं ले जा रहा हूं) – 1dayitwillmake

-1

मैंने बहुत समय और रूपों को आजमाया और खोजा है और निश्चित रूप से मैं एक सरल और तेज़ तक पहुंच गया हूं। यह चाल इस रूप में क्यूबिक बेजियर फ़ंक्शन प्राप्त करती है: पी (यू) = यू^3 (सी 0 + 3 सी 1 -3 सी 2 + सी 3) + यू^2 (3 सी 0 -6 सी 1 + 3 सी 2) + यू (-3 सी 0 + 3 सी 1) + सीजहां सीआई नियंत्रण बिंदु हैं। दूसरा भाग एक्स से बाइनरी खोज के साथ खोज वाई है।

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; 
} 

}

संबंधित मुद्दे