The*_*978 1 math scroll velocity actionscript-3
我正在尝试实现列表对象的动态滚动,但我在确定基于速度应用的摩擦量(持续时间)时遇到问题.
我的applyFriction()方法根据duration属性均匀地降低滚动对象的速度.但是,对于每个动作使用相同的持续时间(IE:1秒)似乎并不自然.
对于具有少量速度的运动(IE:5-10像素),1秒的持续时间看起来很好,但是对于具有大量速度(IE:100+像素)的运动,在1秒的持续时间内施加摩擦,滚动对象将显示为慢和停止更快.
基本上,我试图确定每个运动的适当持续时间,以便小的和大的速度将共享匹配的摩擦力,因此运动物体看起来总是具有恒定的"重量".
是否存在基于不同速度确定动能运动持续时间的通用算法?
注意:我正在使用ActionScript 3.0进行编程,并使用Tween类在一段时间内降低移动对象的速度.
更好的摩擦模型是摩擦力与速度成正比.你需要一个常数来确定力和加速度之间的关系(质量,或多或少).将关系写成差分方程,
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)
Run Code Online (Sandbox Code Playgroud)
因此,如果您希望减速看起来平滑自然,而不是线性降低速度,则需要选择一些略小于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;
Run Code Online (Sandbox Code Playgroud)
我想你会发现这看起来更自然.
如果你想与线性速度降低到接近这一点,那么你会希望你的开支放缓成正比的自然对数的初始速度的时间量.这不会看起来很正确,但它会看起来比你现在的本事有所好转.
(为什么自然对数?因为与速度成比例的摩擦力设定一个第一阶微分方程,它给出了一个EXP(-t/TAU)类型的响应,其中,tau蛋白是该系统的一个特点.从任意衰减的时间速度给定的极限正比于在这样的系统LN(v_init).)
我之前研究过这个问题:为什么 Android 动量滚动感觉不如 iPhone?
幸运的是,一个人已经拿出了一个摄像机,记录了 iPhone 的滚动,并弄清楚了它的作用:存档
轻弹列表及其动量滚动和减速
当我开始工作时,我没有仔细注意 iPhone 上的滚动方式。我只是假设减速是基于牛顿运动定律,即一个运动的物体受到摩擦,它在一段时间后被迫停止。一段时间后,我意识到iPhone(以及后来的 iPad 等 iOS 设备)实际上并非如此。使用相机并捕获各种 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);
Run Code Online (Sandbox Code Playgroud)
事实上,这就是 Apple 自己的PastryKit库(现在是 iAd 的一部分)中实现减速的方式。它将0.95每个动画滴答的滚动速度降低 10 倍(16.7 毫秒,目标为 60 fps)。这对应于 325 毫秒的时间常数。如果您是一个数学极客,那么显然您会意识到滚动速度的指数性质会导致位置的指数衰减。通过一点点涂鸦,最终你会发现
325 = -16.7ms / ln(0.95)
Run Code Online (Sandbox Code Playgroud)
给出动议:

你的问题是关于使用的持续时间。我喜欢 iPhone 的感觉(而不是 Android)。我认为你应该使用1,950 毫秒:
- (1000 ms / 60) / ln(0.95) * 6 = 1950 ms
Run Code Online (Sandbox Code Playgroud)