【问题标题】:Scrolling momentum on mobile devices移动设备上的滚动势头
【发布时间】:2011-03-22 21:42:37
【问题描述】:

我正在尝试获得一种可以在我的移动应用程序中实现的通用平滑滚动机制。

我希望它足够通用,以便可以移植到任何平台,但我目前在 .net Compact Framework 上使用 C#。

我现在正在做的是:

  • 创建一个 Stopwatch 对象(在面板的 ctor 中)
  • 鼠标按下启动秒表并保存当前鼠标点_lastMouse
  • 鼠标移动时,停止秒表并存储velocity = (_lastMouse - curMouse) / Stopwatch.TotalSeconds,然后重置秒表并重新启动
    • 在大多数情况下,Stopwatch.TotalSeconds 介于 0.02 和 0.03 之间
  • 鼠标向上时,我将velocity 值传递给平滑滚动函数,该函数会继续滚动面板,直到到达终点或增加的摩擦力导致速度为 == 0

我的问题在最后一步。 velocity 值通常在 2,000-3,000 像素范围内。速度以每秒像素为单位,因此这是意料之中的。我拿起秒表(它应该仍在运行),停止它,然后我找到从上次鼠标移动经过的时间并将velocity 乘以Stopwatch.TotalSeconds,得到那个距离,然后重置并启动秒表,然后循环回来并开始重新来过。

预期结果是刷新之间的经过时间乘以速度应该得到我应该滚动的像素数(根据最后一次鼠标移动)。我的实际结果是,有时面板会飞起来,有时会移动!逐渐减速很好,只是开始速度关闭了

逻辑有问题吗?我应该做点别的吗?

感谢您的帮助!

【问题讨论】:

  • 所有较新的框架都内置了这个。至少说明您使用的版本,这是一个移动的目标。更好地学习 SilverLight。
  • 是的,我猜所有较新的框架都有内置的面板动量助手。但我使用的是 .net Compact Framewrok 3.5 和 Windows Mobile 6.1 和 6.5(不是 6.5.3)
  • 看看 CodePlex 的流畅和移动。
  • 你知道平台上实际的时序分辨率和精度是多少吗?显然,如果这是不稳定的,那么你会得到有趣的结果。另外,您的滚动有多少差异?即使您以恒定的速度移动,您是否会获得快/慢滚动?
  • 时间分辨率以tick为单位,所以毫秒应该是相当准确的。当以恒定的速度移动时,sparatic 滚动发生的频率较低。如果我在最后做轻弹,那会增加烦躁(有时只是停止,有时飞到底部)

标签: c# mobile physics smooth-scrolling


【解决方案1】:

在我看来,这里有三个可能的不准确来源。首先,作为“A.R.”说,如果你的计时器的粒度不够好,你就会遇到问题。您检查过IsHighResolution 和Frequency 以确保确定没问题吗?

其次,即使你的计时器是完美的,你的位置测量也可能会有些不准确,如果你连续快速地测量两个,那么它可能会伤害你。我的猜测是这没什么大不了的,但是例如如果您使用的是电容式触摸屏,那么当手指抬起时,您的位置可能会随着接触区域的下降而发生变化。

第三,手指的物理运动(或手写笔或鼠标或任何您进行实际输入的东西;我猜是手指)可能表现得并不那么好。在手势结束时,它可能会从大部分水平变为大部分垂直。

通过使用更长的采样周期和也许(两种方式都尝试)忽略最后一个或两个样本,所有这些问题都会得到显着缓解。所以,为最近的样本保留一个小循环缓冲区,当你抬起鼠标时,回顾一下(比如)100 毫秒左右,并用它来决定你的速度。或者,如果您不想保留那么多历史记录,请使用简单的 IIR 过滤器:每次获得样本时,请执行以下操作

filtered_dt = filtered_dt + SMALL*(latest_dt-filtered_dt);
filtered_dx = filtered_dx + SMALL*(latest_dx-filtered_dx);
filtered_dy = filtered_dy + SMALL*(latest_dy-filtered_dy);

据推测,SMALL 应该在 0.2 左右;然后使用filtered_dx/filtered_dt 和filtered_dy/filtered_dt 作为您的速度估计。 (我认为这比每次计算速度并对其进行过滤要好,因为例如,如果您得到一个虚假的小 dt,后者仍然会爆炸。如果有疑问,请尝试两种方式。)

如果您使用 IIR 方法,您可能仍希望让它忽略最后一个样本(如果结果不可靠);如果您记得最新的dt、dx 和dy,您可以通过撤消上次更新来做到这一点:使用(filtered_dt-SMALL*latest_dt)/(1-SMALL) 等。

这是一个现成的建议,可能有效,也可能无效。你提到当手势结束时有一个“轻弹”时,你会得到更不稳定的结果。也许您可以利用它来发挥自己的优势:例如,查看估计的速度在手势结束时的变化速度,如果变化非常快,则稍微增加您使用的速度。

【讨论】:

  • 感谢您的建议!我会在星期一试一试,看看会发生什么。我开始认为我需要加入软糖因素而不是使用纯物理。特别是因为这不是实时设备
  • 好的,我一直在玩你发布的内容,它改进了滚动。这仍然不是我想要的,但你给了我一个很好的方向:)谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-02-26
  • 1970-01-01
  • 2017-05-23
  • 1970-01-01
  • 2019-01-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多