2010-11-23 3 views
1

Ich versuche kinetische Scrolling eines Listenobjekts zu implementieren, aber ich habe ein Problem, die Menge der Reibung (Dauer) basierend auf der Geschwindigkeit zu bestimmen.Dauer für kinetische Scrolling (Momentum) basierend auf Geschwindigkeit?

meine applyFriction() Methode reduziert die Geschwindigkeit des Scroll-Objekts basierend auf einer duration -Eigenschaft gleichmäßig. Die Verwendung derselben Dauer (IE: 1 Sekunde) für jede Bewegung erscheint jedoch nicht natürlich.

Für Bewegungen mit einer kleinen Geschwindigkeit (IE: 5 - 10 Pixel) scheint eine 1 Sekunde Dauer gut zu sein, aber Reibung über eine Sekunde Dauer für Bewegungen mit hoher Geschwindigkeit (IE: 100+ Pixel) beim Scrollen Das Objekt wird langsamer und stoppt viel schneller.

Im Wesentlichen versuche ich, die angemessene Dauer für jede Bewegung zu bestimmen, so dass sowohl kleine als auch große Geschwindigkeitswerte eine übereinstimmende Reibung teilen, so dass das sich bewegende Objekt immer ein konstantes "Gewicht" zu haben scheint.

Gibt es einen allgemeinen Algorithmus zur Bestimmung der Dauer der kinetischen Bewegung basierend auf verschiedenen Geschwindigkeiten?


Anmerkung: ich bin Programmierung in Actionscript 3.0 und die Tween-Klasse unter Verwendung der Geschwindigkeit eines sich bewegenden Objekts über eine Dauer zu reduzieren.

Antwort

6

Ein besseres Modell für Reibung ist, dass die Reibungskraft proportional zur Geschwindigkeit ist. Sie benötigen eine Konstante, um die Beziehung zwischen Kraft und Beschleunigung (Masse, mehr oder weniger) zu bestimmen. Das Schreiben der Beziehungen als Differenzgleichung,

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) 

Also, wenn Sie Ihre Verzögerung wollen glatt und natürlich aussehen, statt linear abnehm Ihre Geschwindigkeit Sie etwas konstant etwas weniger als 1 holen wollen und multiplizieren wiederholt die Geschwindigkeit durch diese Konstante. Natürlich nähert sich dies nur asymptotisch Null, also möchten Sie wahrscheinlich einen Schwellenwert haben, unter dem Sie die Geschwindigkeit einfach auf Null setzen.

So zum Beispiel:

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; 

Ich denke, Sie finden diese viel natürlicher aussieht.

Wenn Sie dies mit einer linearen Geschwindigkeitsreduktion annähern möchten, sollten Sie die Zeit, die Sie mit der Verlangsamung verbringen, proportional zum natürlichen Logarithmus der Anfangsgeschwindigkeit gestalten. Das sieht nicht ganz richtig aus, aber es wird etwas besser aussehen als das, was Sie jetzt haben.

(Warum natürlicher Log? Weil Reibungskraft proportional zur Geschwindigkeit eine Differentialgleichung erster Ordnung aufbaut, die eine exp (-t/tau) -Antwort ergibt, wobei tau eine Eigenschaft des Systems ist Zerfall von einer willkürlichen Geschwindigkeit zu einer gegebenen Grenze ist proportional zu ln (v_init) in einem System wie diesem.)

+0

oder proportional zur Geschwindigkeit im Quadrat ... –

+0

der Tat; Modellierung Reibung kann eine Menge seltsames Verhalten, d. h. Haftreibung (Reibungskraft, die genau extern angelegte Kraft, bis sie eine Schwelle überschreitet), ziehen (v^2), etc., geben. – kwantam

4

Ich hatte dieses Problem schon einmal untersucht: Warum funktioniert Android Impuls Scrollen nicht fühlen so schön wie das iPhone?

Zum Glück a guy already got out a video camera, recorded an iPhone scrolling, and figured out what it does:

Als ich anfing ... zu arbeiten, ich habe nicht darauf geachtet sorgfältig auf die Art und Weise das Scrollen auf dem iPhone funktioniert.Ich nahm nur an, dass die Verzögerung auf Newton’s law of motion basiert, d. H. Ein sich bewegender Körper, der eine Reibung erhält, die nach einer Weile zum Anhalten gezwungen wird. Nach einer Weile wurde mir klar, dass dies tatsächlich nicht ist, wie das iPhone (und später iOS-Geräte wie iPad) tut es. Mit Hilfe einer Kamera und die Erfassung paar Dutzend Bewegung der verschiedenen iOS-Anwendungen scrollen, kam es mir, dass das alles eine Rolle nach der gleichen Menge an Zeit anhalten wird, und zwar unabhängig von der Größe der Liste oder der Geschwindigkeit des Flick. Wie schnell Flick Sie (die die Anfangsgeschwindigkeit des Scrolling bestimmt) bestimmt nur wo die Liste aufhören würde und nicht wenn.

Dies ihn zur stark vereinfachte Mathematik führen:

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); 

In der Tat, das ist, wie die Verzögerung in Apples eigenen PastryKit Bibliothek implementiert wird (und jetzt part of iAd). Es reduziert die Scroll-Geschwindigkeit um einen Faktor von 0.95 für jeden Animations-Tick (16,7 msec, Ausrichtung 60 fps). Dies entspricht einer Zeitkonstante von 325 ms. Wenn Sie ein Mathe-Geek sind, dann erkennen Sie offensichtlich, dass die exponentielle Natur der Scroll-Geschwindigkeit den exponentiellen Abfall in der Position ergibt. Mit ein wenig von scriblling, finden Sie schließlich heraus, dass

325 = -16.7/ln(0.95) 

Giving die Bewegung:

enter image description here


Ihre Frage war über die Dauer zu verwenden. Ich mag, wie sich das iPhone anfühlt (im Gegensatz zu Android). Ich glaube, Sie 1,950 ms verwenden sollten:

- (1000 ms/60)/ln(0.95) * 6 = 1950 ms 
Verwandte Themen