Advertisement
Guest User

Untitled

a guest
Jul 27th, 2017
65
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.71 KB | None | 0 0
  1. /**
  2. * Helper class that simulates some-of-what nativish
  3. * scrolling that continues after dragging (explicit calls to scroll())
  4. * have stopped
  5. */
  6.  
  7. // libraries
  8. import $ from "./Zepto"
  9.  
  10. export default class Scroller {
  11.  
  12.  
  13. constructor($element) {
  14. this.$element = $element
  15.  
  16. // the current scrolling speed (while animating, or average of last movement)
  17. this.speedY = 0
  18.  
  19. // where the scrollable element is scrolled at currently
  20. this.lastY = 0
  21.  
  22. // minimum distance to scroll, beyond lower we don't animate
  23. this.threshold = 0.01
  24.  
  25. // the animation easing; could also use easing function, now just
  26. // exponentially multiply by this factor
  27. this.easing = 0.95
  28.  
  29. // when storing the last moved distance, always use part of this.speedY
  30. // and the other part the current last distance, to somewhat ease
  31. // how an abrupt acceleration or deacceleration just before releasing
  32. // to animating should affect the movement
  33. this.decay = 0.5
  34.  
  35. // store ref to requestAnimationFrame for cancelling
  36. this.animation = null
  37.  
  38. // animation flag; new call to scroll() cancels automatic animation
  39. this.animate = false
  40. }
  41.  
  42.  
  43. /**
  44. * Move to y
  45. */
  46. scroll(y) {
  47. // store how much we moved since last recorded y
  48. let lastSpeed = this.lastY - y
  49.  
  50. // perform the actual scroll
  51. this.$element.scrollTop(y)
  52.  
  53. // cancel perpetual animation frame animation
  54. this.animate = false
  55.  
  56. // on each manual scroll update the speed (distance) at which this manual
  57. // scroll happened, so that when this was the last manual scroll
  58. // we can continue and ease out this scroll
  59. // always balance this current speed with what was last recorded
  60. this.speedY = this.speedY * this.decay + lastSpeed * (1 - this.decay)
  61.  
  62. // record current position
  63. this.lastY = y
  64.  
  65. // trigger perpetual animation; only a new call to scroll will
  66. // cancel it, or having finished animating
  67. this.animation = window.requestAnimationFrame(this.continueScroll.bind(this))
  68. }
  69.  
  70.  
  71. /**
  72. * Perpetual animation callback for scrolling after the last scroll() call
  73. */
  74. continueScroll() {
  75. // check if we should still animate or if the animation got cancelled
  76. if (!this.animate) {
  77. window.cancelAnimationFrame(this.animation)
  78. }
  79.  
  80. if (Math.abs(this.speedY) > this.threshold) {
  81. // scroll by speed, ease out current speed
  82. this.speedY *= this.easing
  83. this.lastY -= this.speedY
  84.  
  85. // stop animating if we reached the end of the scrollable element
  86. if (this.lastY <= 0) {
  87. this.animate = false
  88. }
  89.  
  90. // perform the actual scroll
  91. this.$element.scrollTop(this.lastY)
  92.  
  93. window.requestAnimationFrame(this.continueScroll.bind(this))
  94. } else {
  95. // below threshold, stop animation by not issueing a new frame
  96. // also store status for reference
  97. this.animate = false
  98. }
  99. }
  100.  
  101.  
  102. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement