-
Notifications
You must be signed in to change notification settings - Fork 59
Internals: Flick
This page describes how flicks are calculated and applied within TouchScroll.
Input data for calculating flicks are:
- The last two touch events – the time delta is used to calculate the initial speed, and the vector between event coordinates defines the direction of the flick.
- An average friction factor –
config.flicking.friction
– defining the deceleration factor per millisecond that is used to pre-calculate flick duration and distance. - Minimum speed for the pre-calculation (
config.flicking.minSpeed
). This value is the virtual speed where scrolling would stop – it would continue endlessly when only multiplied with the friction factor.
Variables used are duration (d), minimum speed (s_min), initial speed (s_init), friction (d)
[ duration = \frac{\log \frac{s_min}{\text{initialSpeed}}}{\log \text{friction}} ]
[ distance = \text{initalSpeed} \cdot \sum_{i=o}^{\text{duration}} friction^i = \text{initalSpeed} \cdot \frac{1-friction^{\text{duration}+1}}{1 - \text{friction}} ]
The pre-calculated distance and duration are then applied as transform
and transition-duration
. The transition-timing-function
is configured in config.flick.timingFunc
.
If the flick goes beyond the scroller bounds, the individual portions of duration and distance are calculated using an instance of CubicBezier
project page for each axis. The timing function bezier is divided into two parts. That means, that the flick and bounce animations are completely separated. This is needed to create the rubber-band effect. Bounce duration and distance are then multiplied by config.elasticity.factorFlick
. These two animations/transitions need to be chained in order to appear as a single one.
During the development of TouchScroll I have tried several methods of chaining the two animations, each having individual problems.
-
Using two
<div>
elements (current method): The flick animation is applied to one of the elements and starts immediately. The bounce is applied as transition on the second element, using the flick duration astransition-delay
. Drawbacks of this method is the usage of up to four nested transforms, which has negative impact on rendering performance, especially on weak devices (3G and below). -
Using
@-webkit-keyframes
: I tried to create a set of@-webkit-keyframe
rules for each instance (at instantiation time) and update them for each flick. Changing the individual keyframes seems to trigger an expensive calculation on iPhone 3G, leading to a visible delay before applying the animation. This would be the preferred method. If anybody feels challenged to make this work, try commit 1f95f15245f2c0f4acd915ee6b89a32d64352a39 as a starting point.