2010-11-23 67 views
1

我想实现动态滚动的列表对象,但我有一个问题,确定基于速度应用的摩擦量(持续时间)。基于速度的动力学滚动(动量)的持续时间?

我的applyFriction()方法根据持续时间属性均匀地降低滚动对象的速度。然而,对于每个运动使用相同的持续时间(IE:1秒)并不自然。对于具有少量速度(IE:5 - 10像素)的运动,1秒持续时间显得很好,但对于具有大量速度(IE:100+像素)的运动在1秒持续时间内施加摩擦滚动对象似乎会减慢并停止得更快。本质上,我试图确定每个动作的适当持续时间,以便小和大量的速度将共享一个匹配的摩擦,所以移动的对象将总是有一个恒定的“重量”。

是否有一个通用算法来确定基于不同速度的动力学运动的持续时间?


注:我在ActionScript 3.0编程和使用Tween类,以减少移动物体的通过持续时间的速度。

回答

6

更好的摩擦模型是摩擦力与速度成正比。你需要一个常数来确定力和加速度(质量,或多或少)之间的关系。写作的关系作为差分方程,

F[n] = -gamma * v[n-1] 
a[n] = F[n]/m 
v[n] = v[n-1] + dt * a[n] 
    = v[n-1] + dt * F[n]/m 
    = v[n-1] - dt * gamma * v[n-1]/m 
    = v[n-1] * (1 - dt*gamma/m) 

所以,如果你希望你的减速看起来流畅自然,而不是线性降低你的速度,你要挑一些常量略小于1并多次受到乘以速度这个常数。当然,这只是渐进地接近零,所以你可能想要一个阈值,低于该阈值,你可以将速度设置为零。

因此,举例来说:

v_epsilon = <some minimum velocity>; 
k_frict = 0.9; // play around with this a bit 

while (v > v_epsilon) { 
    v = v * k_frict; 
    usleep(1000); 
} 

v = 0; 

我想你会发现这个看起来更自然。

如果要用线性减速来近似此值,那么您需要使花费减慢的时间与初始速度的自然对数成比例。这看起来不太正确,但它看起来会比现在更好。因为与速度成比例的摩擦力建立了一个一阶微分方程,它给出了exp(-t/tau)类型的响应,其中tau是系统的一个特性。从一个任意速度衰减到一个给定的极限与这样的系统中的ln(v_init)成正比。)

+0

或成正比的速度平方... – 2010-11-24 00:28:20

4

我之前曾经研究过这个问题:为什么Android动量滚动不是感觉和iPhone一样好?

幸运的是,a guy already got out a video camera, recorded an iPhone scrolling, and figured out what it does

当我开始工作......,我没仔细留意滚动适用于iPhone的方式。我只是假设减速是基于Newton’s law of motion,即一个运动的物体接收一段时间后被迫停止的摩擦。过了一段时间,我意识到这实际上是而不是 iPhone(以及后来的iOS设备,如iPad)如何做到这一点。使用相机并捕捉各种iOS应用程序的几十个滚动动作,无论列表的大小或轻弹的速度如何,在相同的时间量之后,所有滚动都会停止。您滑动的速度有多快(决定滚动的初始速度)仅确定,其中列表将停止,而不是,此时

这导致他的大大简化的数学:

amplitude = initialVelocity * scaleFactor; 
step = 0; 

ticker = setInterval(function() { 
    var delta = amplitude/timeConstant; 
    position += delta; 
    amplitude -= delta; 
    step += 1; 
    if (step > 6 * timeConstant) { 
     clearInterval(ticker); 
    } 
}, updateInterval); 

其实,这是减速是如何在苹果自己的PastryKit库中实现(现在part of iAd)。它为每个动画节拍(16.7毫秒,目标为60 fps)将滚动速度降低了0.95。这对应于325毫秒的时间常数。如果你是一个数学怪胎,那么显然你意识到滚动速度的指数性质将导致位置的指数衰减。随着scriblling一点点,最终你会发现,

325 = -16.7/ln(0.95) 

,从而在运动:

enter image description here


你提的问题是关于时间使用。我喜欢iPhone的感觉(与Android相反)。我认为你应该使用1,950 ms

- (1000 ms/60)/ln(0.95) * 6 = 1950 ms