Physics of momentum scrolling

Alexey, EPAM

http://alexeykomov.me

I will speak of

  • GMail for iOS web app algo
  • How it can be useful

Inertia

First law of motion

Bodies with different mass

History

When did native implementations appear?

iOS 5

-webkit-overflow-scrolling: touch

we can leave artificial scrollers behind

...can we?

The problem

Google's GMail solution

How did they implemented this?

We can find out by...

  • Blog post
  • Looking into code

Three "T"s

  • Transform
  • Translate
  • Transition

Let's divide algo to three parts

Part 1 - deceleration

Natural deceleration - in motion

And in physics?

v = v0 +at

x = x0 + v0t +at22

Let's see some code

doMomentum() {
  const transition =
      `transform ${time
      }ms cubic-bezier(0.33, 0.66, 0.66, 1)`;

  this.setTransition(this.element, transition);

  this.setTransform(this.element,
      `translate3d(0, ${newY}px, 0)`);
}

Three "T"s

  • Transform
  • Translate
  • Transition

Code

doMomentum() {
  const transition =
      `transform ${time
      }ms cubic-bezier(0.33, 0.66, 0.66, 1)`;

  this.setTransition(this.element, transition);

  this.setTransform(this.element,
      `translate3d(0, ${newY}px, 0)`);
}

What about time and Δx?

t=v-v0a

Δx=v2-v022a

And acceleration (well... it's deceleration)?

a =0.005pxms2

Code

doMomentum() {
  const transition =
      `transform ${time
      }ms cubic-bezier(0.33, 0.66, 0.66, 1)`;

  this.setTransition(this.element, transition);

  this.setTransform(this.element,
      `translate3d(0, ${newY}px, 0)`);
}

Natural deceleration

cubic-bezier(.33, .66, .66, 1)
Natural deceleration function

Natural deceleration - in motion

Part 2 - snap to bounds

Snapping to bounds

What if we're past the bounds?

snapToBounds() {
  const transition = 'transform' +
    '500ms ease-out';
  this.setTransition(this.element,
      transition);

  this.setTransform(this.element,
      `translate3d(0, ${startY}px, 0)`);
}

Snap to bounds

cubic-bezier(0, 0, .58, 1), ease-out
Ease out function

Snapping to bounds

Part 3 - crossing the bounds

Crossing the bounds

Code for the first part

const valueToLowerCubicBezierWith =
    Math.abs(this.endMomentumVelocity_ /
    velocity) * .33;

const transition =
    `transform ${time}ms cubic-bezier(.33,${
    (.66 - valueToLowerCubicBezierWith)
    },.66,${
    (1 - valueToLowerCubicBezierWith)})`

this.setTransition(this.element, transition);
this.setTransform(this.element,
    `translate3d(0, ${this.contentOffsetY
    }px, 0)`);

What about speed when crossing bounds?
And time?

v=v02-2ax

t=v-v0a

Custom bezier curve depending on end velocity

Flatness degree 1Flatness degree 2Flatness degree 3

Crossing the bounds

We understood Google's algorithm
How can we use it?

Solution

The problem

Solution

It's open-sourced

npm install momentum-scroller

Send pull requests to https://github.com/alexeykomov/momentum-scroller

Demo is here

demo QR code

Presentation is here

presentation QR code

Contacts

http://alexeykomov.me

alexeykcontact@gmail.com

Wanna thank

Thx for your attention