-
-
Save baptistebriel/e5646f7e6a68ef9b281dabc367349b76 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import _ from 'underscore' | |
import App from 'lib/app' | |
import size from 'size' | |
import Mn from 'backbone.marionette' | |
import TweenMax from 'TweenMax' | |
import VirtualScroll from 'virtual-scroll' | |
import prefix from 'vendor-prefix' | |
import template from './template.html' | |
import { props } from 'lib/decorators' | |
const transform = prefix('transform') | |
@props({ | |
template, | |
className: 'VirtualScroll' | |
}) | |
export default class ScrollView extends Mn.View { | |
initialize() { | |
_.bindAll(this, 'event', 'rAF') | |
this.cache = null | |
this.data = { | |
scrollable: true, | |
locked: false, | |
current: 0, | |
target: 0, | |
fixed: 0 | |
} | |
} | |
onRender() { | |
this.addScroll() | |
} | |
addScroll () { | |
this.vs = new VirtualScroll() | |
this.vs.on(this.event, this) | |
TweenMax.ticker.addEventListener('tick', this.rAF, this) | |
} | |
event (e) { | |
if (this.data.locked || this.dead) return | |
this.data.target += Math.round(e.deltaY * -0.5) | |
this.clamp() | |
} | |
clamp () { | |
this.data.target = Math.round(Math.min(Math.max(this.data.target, 0), this.data.height)) | |
} | |
scrollTo (y, lock = false) { | |
if (lock) { | |
this.data.locked = true | |
} | |
this.data.target = y | |
this.clamp() | |
} | |
rAF () { | |
const el = this.ui.section[0] | |
if (!el.style) return | |
const scrollY = this.data.current | |
const scrolling = this.data.target.toFixed() !== this.data.current.toFixed() | |
const fixed = this.data.fixed = scrolling ? 3 : 0 | |
const translateY = this.data.current.toFixed(fixed) | |
this.data.current += (this.data.target - this.data.current) * .15 | |
el.style[transform] = `translate3d(0,-${translateY}px,0)` | |
if (!this.cache) return | |
const threshold = this.options.threshold || 150 | |
this.cache.forEach((data, index) => { | |
const el = this.ui.els[index] | |
const top = data.top - scrollY | |
const bottom = data.bottom - scrollY | |
const inview = top < (size.height + threshold) && bottom > -threshold | |
const direction = top < 0 ? 'top' : 'bottom' | |
if (!data.state && (top > -threshold) && (bottom < (size.height + threshold))) return | |
inview ? this.inView(el, data, direction) : this.outView(el, data, direction) | |
}) | |
} | |
inView (el, data, direction) { | |
if (data.state) return | |
data.state = true | |
const unit = size.height / 2 | |
const duration = Math.random() * (1.3 - 0.5) + 0.5 | |
const delay = Math.random() * (0.1 - 0) + 0 | |
TweenMax.fromTo(el, .2, { | |
opacity: 0, | |
}, { | |
opacity: 1, | |
ease: Linear.easeNone | |
}) | |
TweenMax.fromTo(el, duration, { | |
scale: 1.1, | |
y: unit * (direction === 'top' ? -1 : 1), | |
rotationX: direction === 'top' ? -8 : 8 | |
}, { | |
scale: 1, | |
y: 0, | |
rotationX: 0, | |
ease: Expo.easeOut, | |
delay: delay | |
}) | |
} | |
outView (el, data, direction) { | |
if (!data.state) return | |
data.state = false | |
} | |
onResize(width, height) { | |
const scrollY = Math.round(this.data.target) | |
const bounding = this.ui.bounding[0].getBoundingClientRect() | |
if (this.ui.els && !App.isIE && !App.isFirefox) { | |
this.cache = [] | |
this.ui.els.each((index, el) => { | |
const bounds = el.getBoundingClientRect() | |
const top = bounds.top + scrollY | |
const bottom = bounds.bottom + scrollY | |
this.cache.push({ | |
state: top < size.height && bottom > 0, | |
top: top, | |
bottom: bottom | |
}) | |
}) | |
} | |
this.data.height = (scrollY + bounding.top + bounding.height) - height | |
} | |
onBeforeDestroy() { | |
this.vs.off(this.event, this) | |
this.vs = null | |
TweenMax.ticker.removeEventListener('tick', this.rAF, this) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment