重新创建CSS3过渡Cubic-Bezier曲线 [英] Recreating CSS3 transitions Cubic-Bezier curve

查看:102
本文介绍了重新创建CSS3过渡Cubic-Bezier曲线的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在CSS3过渡中,您可以将计时函数指定为'cubic-bezier:(0.25,0.3,0.8,1.0)'
在该字符串中,您仅指定沿P1和P2点的XY曲线,因为P0和P3始终分别是(0.0,0.0)和(1.0,1.0)。



根据苹果公司的网站:
x [表示]



我的问题是,如何将其映射回javascript中的传统一维T值? ?



-





希望这对某人有帮助!

  function loop(){
var t =(now-animationStartTime)/(animationDuration * 1000);

var曲线= new UnitBezier(Bx,By,Cx,Cy);
var t1 = curve.solve(t,UnitBezier.prototype.epsilon);
var s1 = 1.0-t1;

//使用求解的T
进行rp变数finalPosition.x =(startPosition.x * s1)+(endPosition.x * t1);
var finalPosition.y =(startPosition.y * s1)+(endPosition.y * t1);
}


/ **
*三次贝塞尔曲线的求解器,隐含控制点为(0,0)和(1.0,1.0)
* /
函数UnitBezier(p1x,p1y,p2x,p2y){
//预计算多项式系数
//第一个和最后一个控制点隐含为(0,0)和(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; //精度
UnitBezier.prototype.sampleCurveX = function(t){
return((this.ax * t + this.bx)* t + this.cx)* t;
}
UnitBezier.prototype.sampleCurveY =函数(t){
return((this.ay * t + this.by)* t + this.cy)* t;
}
UnitBezier.prototype.sampleCurveDerivativeX =函数(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;

//首先尝试牛顿方法的一些迭代-通常非常快。
for(t2 = x,i = 0; i< 8; i ++){
x2 = this.sampleCurveX(t2)-x;
如果(Math.abs(x2)< epsilon)
返回t2;
d2 = this.sampleCurveDerivativeX(t2);如果(Math.abs(d2)< epsilon)中断
,则
;
t2 = t2-x2 / d2;
}

//未找到解决方案-使用二等分
t0 = 0.0;
t1 = 1.0;
t2 = x;

如果(t2 如果(t2> t1)返回t1;

而(t0 x2 = this.sampleCurveX(t2);
如果(Math.abs(x2-x)< epsilon)
返回t2;
如果(x> x2)t0 = t2;
else t1 = t2;

t2 =(t1-t0)* .5 + t0;
}

//放弃
return t2;
}

//沿着曲线X找到新的T作为Y的函数
UnitBezier.prototype.solve =函数(x,epsilon){
返回此值。 sampleCurveY(this.solveCurveX(x,epsilon));
}


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

解决方案

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

这篇关于重新创建CSS3过渡Cubic-Bezier曲线的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆