Kri*_*oks 5 c user-interface scroll
如何计算滚动事件的滚动动量?
我知道在结尾滚动的开头必须有两个时间戳.还必须有一个"轴变化"变量,它基本上是没有惯性滚动的量.
这是我当前负责结束滚动的代码:
if ((type == kMXTEnd || type == kMXTMovedOut) && _isScrolling)
{
long int finishTime = MXTimestamp();
printf("SCEnd: Ending scroll at %ld\n",finishTime-_beginTime);
/* scrollX is the change in X axis */
/* finishTime is time from touch down to touch up */
printf(" * Time: %ld ChangeX: %f\n",finishTime,scrollX);
_isScrolling = FALSE;
_originalScrollPoint = _scrollPoint;
}
Run Code Online (Sandbox Code Playgroud)
是否有可能计算出" 惯性加成 "?就像惯性所获得的额外偏移量一样,除了主要滚动值之外我还可以滚动.或者我需要获得其他变量吗?
我需要这个,因为我正在编写自己的UI工具包,它实际上不是基于任何东西.
以下是我取得的良好效果。
在每个鼠标拖动事件(或触摸事件)上,都存储速度(因此移动量除以自上一帧以来的时间)和时间戳。您只需要最后一个,所以只有两个变量。
释放鼠标/触摸时,请检查最近的时间戳是否足够近(我使用0.3秒)。如果是这样,则将可变惯性速度设置为上一次计算出的速度;否则,将其设置为0以防止在用户仔细选择位置时滚动。
然后在每次更新时(通过计时器或每个渲染调用,具体取决于您的渲染方式),按惯性速度* INERTIA_SCROLL_FACTOR(我使用0.9)滚动,并将惯性速度乘以INERTIA_ACCELERATION(我使用0.98)。
您可能需要添加一个阈值,因此如果惯性速度变得太小,滚动将停止。我使用1作为阈值,因为我的渲染库使用浮点数作为坐标。如果坐标是整数,则其自身将降为零。
要记住的一件事是,惯性速度可以是正的也可以是负的,具体取决于方向。
因此,用伪代码:
OnMouseMove:
inertialVelocity = moveDistance / (now - timeOfLastEvent)
timeOfLastEvent = now
OnMouseUp:
if (now - timeSinceLastEvent > 0.3f)
inertialVelocity = 0
OnTimer/OnRender:
// timeDelta is needed only when doing this on render events, just to make
// it independent of the render speed. It is the time since the previous render
scrollPosition += inertialVelocity * INERTIA_SCROLL_FACTOR * timeDelta
inertialVelocity *= INERTIA_ACCELERATION * timeDelta
// Keep in mind that velocity can be negative as well, hence the abs
if (abs(inertialVelocity) < INERTIA_THRESHOLD)
inertialVelocity = 0
Run Code Online (Sandbox Code Playgroud)
您可以使用"最近的轴更改"队列来模拟此情况.
如果您使用相应的时间戳存储说明最后半秒的更改,则可以测试队列是否长于某个值N(即,如果用户拖动它比平时更快).你知道最后半秒的时间,也就是你可以获得速度的时间.
将速度缩放到合理的范围(例如,对于15px/.5秒,映射到~25px/sec)并且每隔几毫秒应用负加速度(也适用于上述示例,比如说-20px/sec)(或者只要您的系统能够轻松处理它,请不要过度使用它.
然后运行一个计时器,更新每个tick(speed+=accel*time_scale)的速度,然后是position(position+=speed*time_scale).当速度达到0(或低于它)时,杀死计时器.