2012-06-13 56 views
4

我想要一个相当于UIViewAnimationCurveEaseInOut的缓动函数,但没有看到Apple公开这个功能。我试过the easeInOutQuad function posted here没有成功。我该功能的Objective-C的版本是:轻松缓出功能

-(float) getEaseInOutValueWithElapsedMillis: (float) t startValue: (float) b endValue: (float) c andTotalMillis: (float) d { 
    float value =0.0f; 

    if ((t/=d/2.0f) <1.0f) 
     value =c/2.0f*t*t + b; 
    else 
     value =-c/2.0f * ((--t)*(t-2.0f) - 1.0f) + b; 

    debug(@"t=%f b=%f c=%f d=%f value=%f", t, b, c, d, value); 
    return value; 
} 

和登录的结果是:

当开始值小于终值:

t=0.066467 b=110.000000 c=225.000000 d=500.000000 value=110.497017 
t=0.133133 b=110.000000 c=225.000000 d=500.000000 value=111.993996 
t=0.199799 b=110.000000 c=225.000000 d=500.000000 value=114.490944 
... 
t=0.999786 b=110.000000 c=225.000000 d=500.000000 value=222.451935 
t=0.066452 b=110.000000 c=225.000000 d=500.000000 value=236.954926 
t=0.133118 b=110.000000 c=225.000000 d=500.000000 value=250.457932 
... (note that value shot right past c) 
t=0.866440 b=110.000000 c=225.000000 d=500.000000 value=332.993195 
t=0.933105 b=110.000000 c=225.000000 d=500.000000 value=334.496582 
t=0.999771 b=110.000000 c=225.000000 d=500.000000 value=335.000000 

而且100%的值最终为b + c,而不是c。

当开始值大于结束值时:

t=0.047389 b=225.000000 c=110.000000 d=700.000000 value=225.123520 
t=0.095008 b=225.000000 c=110.000000 d=700.000000 value=225.496460 
... 
t=0.904504 b=225.000000 c=110.000000 d=700.000000 value=334.498413 
t=0.952122 b=225.000000 c=110.000000 d=700.000000 value=334.873932 
t=0.999740 b=225.000000 c=110.000000 d=700.000000 value=335.000000 

再次,100%值最终成为B + C,而不是C。

也许我已经破坏了代码。我怎样才能实现舒适的缓解?

+0

JavaScript与C具有相同的运算符优先级吗?我首先将这些计算中的一部分解压缩到中间值并在其周围洒一些括号。如果((t/= d/2))'只是毛。 –

+0

好的建议。我不知道这两种语言的运算符优先级是否相同。根据记录的输出结果看来,t似乎是正确的。 – user371320

+0

有趣的事实。 ECMAScript语言规范似乎没有提及运营商的优先级。 – user371320

回答

1

有点晚了,但在这里,它很快。在操场

运行这样的:

import UIKit 

var sValue: CGFloat = 0 
var eValue: CGFloat = 100 
var tDuration: CGFloat = 100 
var eTime: CGFloat = 0 

var currentValue: CGFloat = 0 

func easeInOutQuad (percentComplete: CGFloat, elapsedTimeMs: CGFloat, startValue: CGFloat, endValue: CGFloat, totalDuration: CGFloat) -> CGFloat { 
    var newElapsedTimeMs = elapsedTimeMs 
    newElapsedTimeMs /= totalDuration/2 

    if newElapsedTimeMs < 1 { 
     return endValue/2*newElapsedTimeMs*newElapsedTimeMs + startValue 
    } 
    newElapsedTimeMs = newElapsedTimeMs - 1 
    return -endValue/2 * ((newElapsedTimeMs)*(newElapsedTimeMs-2) - 1) + startValue 
} 

for i in eTime...tDuration { 
    currentValue = easeInOutQuad(0, CGFloat(i), sValue, eValue, tDuration) 
} 
+0

不适用于swift 2.2 – brainray

1

我想一个宽松相当于 UIViewAnimationCurveEaseInOut功能,但没有看到苹果暴露了 的功能。

苹果通过暴露在[CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseInEaseOut]CAMediaTimingFunction您可以拨打getControlPointAtIndex:values:得到控制点。你会发现它是一个带控制点(0,0),(0.42,0),(0.58,1),(1,1)的立方贝塞尔曲线。

这就给了你一个贝塞尔函数f(n)该地块为value二维图沿y方向,对time沿x方向。所以要得到正确的值只需解决n其中x = time和读取的值。

具体地,在此功能:

f.x(n) = (1-n)^3 * 0 + 3(1-n)^2 * n * 0.42 + 3(1-n) * n^2 * 0.58 + n^3 * 1 
     = 3(1-n)^2 * n * 0.42 + 3(1-n) * n^2 * 0.58 + n^3 
     = 1.26(1 - 2n + n^2) * n + 1.74 (1 - n) * n^2 + n^3 
     = 1.26n - 2.52n^2 + 1.26n^3 + 1.74n^2 - 1.74n^3 + n^3 
     = 1.26n - 0.78n^2 + 0.52n^3 

(声明:即兴写出;请检查)

在时间0.5得到的值,在解决对于n:

0.5 = 1.26n - 0.78n^2 + 0.52n^3 

然后将其插入等效的f.y(n)There's a formula to solve a cubic但进入这是略有涉及,所以(一)阅读维基百科文章,并使用公式;或者(ii)写一个数字求解器,例如,通过二进制搜索。这种立方体的表现非常好,每次只有一种解决方案。