Slide 1

Slide 1 text

Smooth Animation on Mobile Web From Kinetic Scrolling to Cover Flow @ariyahidayat June 26, 2014

Slide 2

Slide 2 text

Newton’s laws of motion

Slide 3

Slide 3 text

Steve Jobs, 2007

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

Optimized JavaScript requestAnimationFrame Event throttling

Slide 7

Slide 7 text

ariya.github.io/kinetic #kineticscrolling https://speakerdeck.com/ariya

Slide 8

Slide 8 text

Drag-and-Scroll 1

Slide 9

Slide 9 text

http://ariya.github.io/kinetic/1/

Slide 10

Slide 10 text

Text “Clipped” via overflow:hidden http://ariya.ofilabs.com/2013/08/javascript-kinetic-scrolling-part-1.html 80 lines of JavaScript Illusion of scrolling

Slide 11

Slide 11 text

No Native Browser Scrolling view = document.getElementById('view'); if (typeof window.ontouchstart !== 'undefined') { view.addEventListener('touchstart', tap); view.addEventListener('touchmove', drag); view.addEventListener('touchend', release); } view.addEventListener('mousedown', tap); view.addEventListener('mousemove', drag); view.addEventListener('mouseup', release); Intercept mouse events Intercept touch events

Slide 12

Slide 12 text

Steady Pressed Scrolling touchstart touchend touchmove touchend

Slide 13

Slide 13 text

Tap vs Release function tap(e) { pressed = true; reference = ypos(e); e.preventDefault(); e.stopPropagation(); return false; } function release(e) { pressed = false; e.preventDefault(); e.stopPropagation(); return false; }

Slide 14

Slide 14 text

Drag: Delta + CSS Transform if (pressed) { y = ypos(e); delta = reference - y; reference = y; scroll(offset + delta); } function scroll(y) { offset = (y > max) ? max : (y < min) ? min : y; view.style[xform] = 'translateY(' + (-offset) + 'px)'; }

Slide 15

Slide 15 text

Scroll Threshold delta = reference - y; if (delta > 2 || delta < -2) { reference = y; scroll(offset + delta); }

Slide 16

Slide 16 text

User taps the screen pressed = true (touch) reference = 20 (view) offset = 100 User drags 7 px up (touch) y = 13 (touch) delta = 7 (view) offset = 107 translate the document by 7 px User releases finger pressed = false

Slide 17

Slide 17 text

Drag-and-Scroll Technique Intercept browser events Track position + apply CSS transform Illusion of scrolling

Slide 18

Slide 18 text

Kinetic F/X 2

Slide 19

Slide 19 text

http://ariya.github.io/kinetic/2/ Momentum Effect Flick List Kinetic Scrolling

Slide 20

Slide 20 text

http://ariya.ofilabs.com/2013/11/javascript-kinetic-scrolling-part-2.html Automatic scrolling Manual scrolling 120 lines of JavaScript

Slide 21

Slide 21 text

Steady touchstart Pressed Manual Scrolling Automatic Scrolling touchend timer tick touchmove touchend and zero speed touchend and positive speed timer tick decelerate to zero speed touchstart

Slide 22

Slide 22 text

Tap Drag Release (Quick) Move Release Flick Gesture

Slide 23

Slide 23 text

Manual Scrolling Automatic Scrolling Track touch position Scroll the view Compute the “launch” velocity Scroll the view Reduce the velocity

Slide 24

Slide 24 text

Continuous Velocity Tracking function tap(e) { pressed = true; reference = ypos(e); velocity = amplitude = 0; frame = offset; timestamp = Date.now(); clearInterval(ticker); ticker = setInterval(track, 100); e.preventDefault(); e.stopPropagation(); return false; } Call track() 10 times/second Rate throttling

Slide 25

Slide 25 text

Velocity = Change of Position function track() { var now, elapsed, delta, v; now = Date.now(); elapsed = now - timestamp; timestamp = now; delta = offset - frame; frame = offset; v = 1000 * delta / (1 + elapsed); velocity = 0.8 * v + 0.2 * velocity; } instantaneous velocity ~ 100 ms optional filter

Slide 26

Slide 26 text

Automatic Scrolling Exponential decay time scroll offset

Slide 27

Slide 27 text

Slow Down, a.k.a. Deceleration time velocity

Slide 28

Slide 28 text

Stopped Decelerating

Slide 29

Slide 29 text

No content

Slide 30

Slide 30 text

Half-Life velocity reduced to 50%

Slide 31

Slide 31 text

Time Constant velocity reduced by 63%

Slide 32

Slide 32 text

Scroll offset at a given time Final scroll offset Amplitude (how far the final scroll offset is) Time constant

Slide 33

Slide 33 text

amplitude = 0.7 * velocity; target = offset + amplitude; requestAnimationFrame(autoScroll); Setup for Automatic Scrolling

Slide 34

Slide 34 text

function autoScroll() { var elapsed = Date.now() - timestamp; scroll(target - amplitude * Math.exp(-elapsed / timeConstant)); requestAnimationFrame(autoScroll); } Continuous Automatic Scrolling

Slide 35

Slide 35 text

6 × time constant The list will stop after 1.95 seconds

Slide 36

Slide 36 text

The flick (=launch velocity) determines how far the list will stop It does not impact when the list will stop scrolling 1 2

Slide 37

Slide 37 text

Exponential Decay vs Cubic Bézier Position Exponential decay Cubic bézier Velocity time time

Slide 38

Slide 38 text

Exponential Decay vs Cubic Bézier t

Slide 39

Slide 39 text

Frame Rate HUD in Chrome chrome://flags http://ariya.ofilabs.com/2013/03/frame-rate-hud-on-chrome-for-android.html

Slide 40

Slide 40 text

Kinetic Scrolling Unmasked Intercept browser events Track position + velocity Kinetic F/X Auto scroll with exponential decay

Slide 41

Slide 41 text

Snap-to-Grid 3

Slide 42

Slide 42 text

http://ariya.github.io/kinetic/3/ List items Target position

Slide 43

Slide 43 text

Date Picker The scrolling can’t stop halfway

Slide 44

Slide 44 text

Adjustment of Final Position http://ariya.ofilabs.com/2013/12/javascript-kinetic-scrolling-part-3.html Possible choices

Slide 45

Slide 45 text

As Simple As... function autoScroll() { var elapsed = Date.now() - timestamp; scroll(target - amplitude * Math.exp(-elapsed / timeConstant)); target = Math.round(target / snap) * snap; requestAnimationFrame(autoScroll); }

Slide 46

Slide 46 text

As Simple As... function autoScroll() { var elapsed = Date.now() - timestamp; scroll(target - amplitude * Math.exp(-elapsed / timeConstant)); target = Math.round(target / snap) * snap; requestAnimationFrame(autoScroll); } Integer multiples of snap

Slide 47

Slide 47 text

Hydrogen Energy Levels E Discrete levels Classical physics Quantum mechanics

Slide 48

Slide 48 text

Swipe with Parallax 4

Slide 49

Slide 49 text

No content

Slide 50

Slide 50 text

No content

Slide 51

Slide 51 text

http://ariya.github.io/kinetic/4/

Slide 52

Slide 52 text

Different Distance, Different Speed http://ariya.ofilabs.com/2013/12/javascript-kinetic-scrolling-part-4.html

Slide 53

Slide 53 text

function scroll(offset) { var slow = Math.round(offset / 2); var fast = Math.round(offset); ... } snap = screen width

Slide 54

Slide 54 text

Model View Controller Kinetic Model Touch events View DOM properties “Number” Event Handler

Slide 55

Slide 55 text

Cover Flow 5

Slide 56

Slide 56 text

CSS with GPU Compositing http://ariya.ofilabs.com/2013/06/optimizing-css3-for-gpu-compositing.html

Slide 57

Slide 57 text

http://ariya.github.io/kinetic/5/

Slide 58

Slide 58 text

No content

Slide 59

Slide 59 text

200 lines of JavaScript http://ariya.ofilabs.com/2014/01/javascript-kinetic-scrolling-part-5-cover-flow-effect.html No transformation translateX(-110px) translateZ(-150px) rotateY(60deg) translateX(110px) translateZ(-150px) rotateY(-60deg)

Slide 60

Slide 60 text

translateX(-110px) translateX(-110px) translateZ(-150px) translateX(-110px) translateZ(-150px) rotateY(60deg) Perspective 3-D

Slide 61

Slide 61 text

Swipe time translateX(0px) translateX(-110px) time translateZ(0px) translateZ(-150px) time rotateY(60deg) rotateY(0deg)

Slide 62

Slide 62 text

Model View Decoupling Touch events 3-D View CSS transform

Slide 63

Slide 63 text

Final Words

Slide 64

Slide 64 text

Kinetic Scrolling Parallax Effect

Slide 65

Slide 65 text

Thank You shapesecurity.com @ariyahidayat