Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * Helper class that simulates some-of-what nativish
- * scrolling that continues after dragging (explicit calls to scroll())
- * have stopped
- */
- // libraries
- import $ from "./Zepto"
- export default class Scroller {
- constructor($element) {
- this.$element = $element
- // the current scrolling speed (while animating, or average of last movement)
- this.speedY = 0
- // where the scrollable element is scrolled at currently
- this.lastY = 0
- // minimum distance to scroll, beyond lower we don't animate
- this.threshold = 0.01
- // the animation easing; could also use easing function, now just
- // exponentially multiply by this factor
- this.easing = 0.95
- // when storing the last moved distance, always use part of this.speedY
- // and the other part the current last distance, to somewhat ease
- // how an abrupt acceleration or deacceleration just before releasing
- // to animating should affect the movement
- this.decay = 0.5
- // store ref to requestAnimationFrame for cancelling
- this.animation = null
- // animation flag; new call to scroll() cancels automatic animation
- this.animate = false
- }
- /**
- * Move to y
- */
- scroll(y) {
- // store how much we moved since last recorded y
- let lastSpeed = this.lastY - y
- // perform the actual scroll
- this.$element.scrollTop(y)
- // cancel perpetual animation frame animation
- this.animate = false
- // on each manual scroll update the speed (distance) at which this manual
- // scroll happened, so that when this was the last manual scroll
- // we can continue and ease out this scroll
- // always balance this current speed with what was last recorded
- this.speedY = this.speedY * this.decay + lastSpeed * (1 - this.decay)
- // record current position
- this.lastY = y
- // trigger perpetual animation; only a new call to scroll will
- // cancel it, or having finished animating
- this.animation = window.requestAnimationFrame(this.continueScroll.bind(this))
- }
- /**
- * Perpetual animation callback for scrolling after the last scroll() call
- */
- continueScroll() {
- // check if we should still animate or if the animation got cancelled
- if (!this.animate) {
- window.cancelAnimationFrame(this.animation)
- }
- if (Math.abs(this.speedY) > this.threshold) {
- // scroll by speed, ease out current speed
- this.speedY *= this.easing
- this.lastY -= this.speedY
- // stop animating if we reached the end of the scrollable element
- if (this.lastY <= 0) {
- this.animate = false
- }
- // perform the actual scroll
- this.$element.scrollTop(this.lastY)
- window.requestAnimationFrame(this.continueScroll.bind(this))
- } else {
- // below threshold, stop animation by not issueing a new frame
- // also store status for reference
- this.animate = false
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement