Pro Yearly is on sale from $80 to $50! »

Cover Flow in JavaScript and CSS 3-D

Cover Flow in JavaScript and CSS 3-D

Presented at HTML5 Developer Conference Autumn 2014.

With the support for buttery-smooth GPU-accelerated 3-d effect with CSS, modern browsers allow an implementation of a stunning fluid and dynamic user interface. To ensure that the performance is still at the 60 fps level, certain best practices needs to be followed: fast JavaScript code, usage of requestAnimationFrame, and optimized GPU compositing.

This talk aims to show a step-by-step guide to implement the infamous Cover Flow effect with JavaScript and CSS 3-D. We will start with the basic principle of custom touch-based scrolling technique, the math & physics behind momentum effect, and the use of perspective transformation to build a slick interface. Don’t worry, the final code is barely 200 lines!

0284b8950e0f4a57bcc092d4dbb98d97?s=128

Ariya Hidayat

October 21, 2014
Tweet

Transcript

  1. Cover Flow in JavaScript and CSS 3-D @ariyahidayat Oct 21,

    2014 #HTML5DevConf
  2. Steve Jobs, 2007

  3. Newton’s laws of motion

  4. None
  5. Optimized JavaScript requestAnimationFrame Event throttling

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

  7. Drag-and-Scroll 1

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

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

    of scrolling
  10. 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
  11. Steady Pressed Scrolling touchstart touchend touchmove touchend

  12. 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; }
  13. 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)'; }
  14. Scroll Threshold delta = reference - y; if (delta >

    2 || delta < -2) { reference = y; scroll(offset + delta); }
  15. 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
  16. Drag-and-Scroll Technique Intercept browser events Track position + apply CSS

    transform Illusion of scrolling
  17. Kinetic F/X 2

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

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

  20. 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
  21. Tap Drag Release (Quick) Move Release Flick Gesture

  22. Manual Scrolling Automatic Scrolling Track touch position Scroll the view

    Compute the “launch” velocity Scroll the view Reduce the velocity
  23. 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
  24. 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
  25. Automatic Scrolling Exponential decay time scroll offset

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

  27. Stopped Decelerating

  28. Time Constant velocity reduced by 63%

  29. Scroll offset at a given time Final scroll offset Amplitude

    (how far the final scroll offset is) Time constant
  30. amplitude = 0.7 * velocity; target = offset + amplitude;

    requestAnimationFrame(autoScroll); Setup for Automatic Scrolling
  31. function autoScroll() { var elapsed = Date.now() - timestamp; scroll(target

    - amplitude * Math.exp(-elapsed / timeConstant)); requestAnimationFrame(autoScroll); } Continuous Automatic Scrolling
  32. 6 × time constant The list will stop after 1.95

    seconds
  33. The flick (=launch velocity) determines how far the list will

    stop It does not impact when the list will stop scrolling 1 2
  34. Kinetic Scrolling Unmasked Intercept browser events Track position + velocity

    Kinetic F/X Auto scroll with exponential decay
  35. Snap-to-Grid 3

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

  37. Date Picker The scrolling can’t stop halfway

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

  39. 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); }
  40. 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
  41. Swipe with Parallax 4

  42. None
  43. None
  44. http://ariya.github.io/kinetic/4/

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

  46. function scroll(offset) { var slow = Math.round(offset / 2); var

    fast = Math.round(offset); ... } snap = screen width
  47. Cover Flow 5

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

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

  50. None
  51. 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)
  52. translateX(-110px) translateX(-110px) translateZ(-150px) translateX(-110px) translateZ(-150px) rotateY(60deg) Perspective 3-D

  53. Model View Decoupling Touch events 3-D View CSS transform

  54. Final Words

  55. Kinetic Scrolling Parallax Effect

  56. Thank You shapesecurity.com @ariyahidayat