2

モバイル アプリケーションに実装できる一般的なスムーズ スクロール メカニズムを取得しようとしています。

任意のプラットフォームに移植できるように十分に汎用的であることを望んでいますが、現在、.net Compact Framework で C# を使用しています。

私が今していることは次のとおりです。

  • (パネルの ctor に) Stopwatch オブジェクトを作成します。
  • マウスダウンでストップウォッチを開始し、現在のマウスポイントを保存します_lastMouse
  • マウスの移動時に、ストップウォッチを停止して保存しvelocity = (_lastMouse - curMouse) / Stopwatch.TotalSeconds、ストップウォッチをリセットして再度開始します
    • ほとんどの場合Stopwatch.TotalSeconds、0.02 から 0.03 の間です
  • マウスを離すと、velocity値をスムーズ スクロール関数に渡します。その関数は、端に到達するか、摩擦の増加によって速度が == 0 になるまで、パネルをスクロールし続けます。

私の問題は最終段階にあります。値は通常、velocity2,000 ~ 3,000 ピクセルの範囲内です。速度は 1 秒あたりのピクセル単位であるため、これは予想されることです。ストップウォッチ (まだ実行されているはずです) を取り、それを停止し、最後のマウスの動きからの経過時間を見つけて を掛けvelocityStopwatch.TotalSecondsその距離を取得し、ストップウォッチをリセットして開始し、ループバックして最初からやり直します。

予想される結果は、更新間の経過時間に速度を掛けた値が、スクロールする必要がある (最後のマウスの動きに応じた) ピクセル数になることです。私の実際の結果は、時々パネルが飛んだり、時には辛うじて動いたりすることです! 緩やかな減速は問題ありません。オフになっているのは最初の速度だけです

ロジックに欠陥はありますか?私は何か他のことをすべきですか?

助けてくれてありがとう!

4

1 に答える 1

1

ここには、3 つの不正確な原因が考えられるように思われます。まず、「AR」が言ったように、タイマーの粒度が十分でない場合、問題が発生します。確認して、問題ないことを確認IsHighResolutionしましたか?Frequency

第二に、タイマーが完璧であっても、位置測定に不正確さがある可能性があり、非常に短い時間で 2 つ連続して測定すると、問題が発生する可能性があります。これは大したことではないと思いますが、たとえば、静電容量式タッチスクリーンを使用している場合、指が離されると、接触領域が下がるにつれて位置が変化する可能性があります.

第 3 に、指 (またはスタイラス、マウス、または実際の入力を行っているもの; 私は指を推測します) の物理的な動きは、それほど適切に動作しない可能性があります。ジェスチャの最後に、ほぼ水平からほぼ垂直に変化することがあります。

これらの問題はすべて、より長いサンプリング期間を使用し、おそらく(両方の方法で試してみてください) 最後のサンプルまたは 2 つのサンプルを無視することで大幅に軽減されます。したがって、最近のサンプルの小さな循環バッファーを保持し、マウスアップを取得したら (たとえば) 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_dtfiltered_dy/filtered_dtます。(これは、毎回速度を計算してフィルタリングするよりも優れていると思います。たとえば、誤って小さい が得られた場合、後者はまだ爆破されるためですdt。疑わしい場合は、両方の方法を試してください。)

IIR アプローチを使用する場合でも、最後のサンプルが信頼できないことが判明した場合は、それを無視させたい場合があります。dt最新のdxを覚えている場合はdy、最後の更新を元に戻すことでそれを行うことができます:(filtered_dt-SMALL*latest_dt)/(1-SMALL)などを使用します。

これは、うまくいくかもしれないしうまくいかないかもしれない壁から離れた提案です。ジェスチャの最後に「フリック」があると、より不安定な結果が得られるとおっしゃいました。おそらく、それを有利に利用することができます。たとえば、ジェスチャの最後に推定速度がどれだけ急速に変化しているかを見て、それが非常に急速に変化している場合は、使用する速度をいくらか上げます。

于 2011-03-25T22:15:59.520 に答える