2009-11-27 118 views
21

创建动态滚动实现的一些好算法是什么?该功能将在自定义UI列表中进行测试。虽然我针对移动设备(那些内置此功能的设备),但来自不同编程领域的任何算法或代码示例也可能适用。实现动态滚动的算法

回答

23

我最近自己实现了一个。这些是我采取的步骤。

  1. 你需要衡量你的光标(或鼠标光标或手指)
  2. 实现一个简单的粒子物理环路的速度。有关如何做到这一点的信息可以通过从滚动面的宽度派生数学发现​​here
  3. 给你的粒子“边界”,和你的视口的宽度
  4. 不断添加鼠标速度和之间的区别粒子速度与粒子速度的关系,所以粒子的速度只要移动就“匹配”鼠标的速度。
  5. 一旦用户抬起手指,请停止执行第4步。物理循环负责处理惯性。
  6. 添加您的个人兴趣,如“保险杠”边距,以及根据zeno运算悖论计算的平滑滚动“锚点”。
  7. 我差点忘了:从上面获取坐标,并将其用作滚动平面的位置。

我可能很快就会开源代码。你多久需要这个?

编辑:改变了链接。对不起,指出了一些错误的页面。 edit2:还是不?无论如何,我链接到的原始页面是当前链接页面上的第一个链接。

+2

我会尽力在几周内实现这一点。现在我只是在想它。感谢您的答复。如果您决定开放您的解决方案,请在此处发布一些消息。 – 2009-11-27 23:07:34

+0

链接长时间死亡现在:( – 2016-08-03 08:45:33

-1

嗯,我认为它会像a)获取用户滚动b)速度的速度,当他离开他的手指时,自动滚动列表但自动滚动列表,但以降低的速度和用户的初始速度。

21

因为这是最初问到的,所以我已经仔细阅读了pastrykit的源代码,在这个框架中,苹果已经完全复制了它们在JavaScript中的动态滚动。没有粒子物理循环 - 触摸的速度是在手指抬起的时刻测量的。从这一点开始,使用速度作为输入参数的简单缓动功能来动画滚动。

13

我刚刚添加了一个滚动窗口小部件到我的移动GUI框架,所以我想我会在这里分享我的解决方案。

由于这是一个相当复杂的问题,我决定把它划分成更小一些独立的子任务,具体如下:

  1. 基本滚动功能:这个任务在处理中最简单的拖动事件包括这是通过根据拖拽距离和方向来滚动内容的方式。这是相对简单的实现,唯一棘手的方面是知道什么时候开始拖动操作与何时将点击事件传递给可滚动区域内的子部件。

  2. 滚动惯性:这是最具挑战性的。这里的想法是,在用户抬起手指后,应该继续滚动一段时间,放慢速度直到完全停止。为此,我需要了解滚动速度。不幸的是,从单个样本计算速度并不准确,所以当用户滚动时,我会在循环缓冲区中记录最后N个运动事件以及每个事件发生的时间。我发现N = 4可以在iPhone和HP TouchPad上正常工作。当手指抬起时,我可以根据记录的动作计算惯性滚动的近似开始速度。我定义了一个负加速度系数并使用了标准运动公式(请参阅here),以便很好地滚动滚动条。如果滚动位置在仍然运动时到达边界,我只需将速度重置为0以防止它超出范围(紧接着的是突然停止)。

  3. 灵活的滚动限制:当滚动到达结尾时,我不想进入突然停止状态,而是希望小部件滚动某些内容,但会提供阻力。为此,我将两端允许的滚动范围扩展了一个我定义为小部件尺寸函数的数量。我发现在每一端添加一半宽度或高度的效果很好。让滚动感觉提供一些阻力的技巧是在显示的滚动位置超出范围时调整显示的滚动位置。我使用了缩放加减速功能(有一些很好的缓动功能here)。

  4. 弹簧行为:因为现在可以滚动到有效范围之外,所以我需要一种方法在用户将其移出范围时将滚动条移回有效位置。这可以通过调整滚轮停止在超出范围位置时的滚动偏移来实现。我发现调整功能给人一种很好看的弹性外观,就是将距离当前位置到理想位置的距离除以一个常数,并将偏移量移动该量。不断变慢的运动越大。

  5. 滚动条:最后一点是添加叠加滚动条,当滚动开始时淡入淡出,结束时淡入淡出。

+1

可以请你分享滚动惯量代码吗?谢谢。 – SpaceDog 2013-09-17 06:09:13

1

你看过Robert Penner的宽松功能吗?

http://www.robertpenner.com/easing/

IIRC这些原本为ActionScript和已经存在了很长一段时间。

+0

我从来没有见过这些!所以非常有用。+1 – 2015-08-11 12:59:47