Last active
February 15, 2020 20:35
-
-
Save jesperlandberg/f30fc32cb48425127c5df9804b457e2d to your computer and use it in GitHub Desktop.
This file contains hidden or 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 gsap from 'gsap' | |
| import VirtualScroll from 'virtual-scroll' | |
| import Events from './Events' | |
| // Raf | |
| gsap.ticker.fps(-1) | |
| gsap.ticker.add(tick) | |
| function tick() { | |
| Events.emit('tick') | |
| } | |
| // Scroll | |
| const isWindows = (["Win32", "Win64", "Windows", "WinCE"].indexOf(window.navigator.platform) !== -1) | |
| const vs = new VirtualScroll({ | |
| mouseMultiplier: isWindows ? 1.1 : 0.45, | |
| touchMultiplier: 3, | |
| firefoxMultiplier: isWindows ? 40 : 90, | |
| passive: true | |
| }) | |
| vs.on(scroll) | |
| function scroll({ deltaY ) { | |
| Events.on('scroll', { y: deltaY }) | |
| } | |
| // Resize | |
| window.addEventListener('resize', () => Events.emit('resize')) |
This file contains hidden or 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 e from '@unseenco/e' | |
| const Events = new e() | |
| export default Events |
This file contains hidden or 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 gsap from 'gsap' | |
| import { Events } from '@/events' | |
| export default class { | |
| ui = {} | |
| constructor(el = document.body) { | |
| this.el = el | |
| this.ui.elems = [...this.el.querySelectorAll('[data-smooth-item]')] | |
| this.state = { | |
| target: 0, | |
| current: 0, | |
| scroll: 0, | |
| threshold: 100, | |
| resize: false, | |
| wh: window.innerHeight | |
| } | |
| this.init() | |
| } | |
| init() { | |
| this.setBounds() | |
| this.setElems() | |
| this.addEvents() | |
| } | |
| addEvents() { | |
| Events.on('scroll', this.scroll) | |
| Events.on('tick', this.run) | |
| Events.on('resize', this.resize) | |
| } | |
| setBounds() { | |
| const { height } = this.el.getBoundingClientRect() | |
| const state = this.state | |
| state.max = height - state.wh | |
| } | |
| setElems() { | |
| const { threshold, wh } = this.state | |
| this.elems = this.ui.elems.map(el => { | |
| el.style.transform = 'translate3d(0, 0, 0)' | |
| const { top, bottom } = el.getBoundingClientRect() | |
| return { | |
| el, | |
| start: top - wh - threshold, | |
| end: bottom + threshold, | |
| speed: parseFloat(el.dataset.smoothItem || 1) | |
| } | |
| }) | |
| } | |
| resize = () => { | |
| const state = this.state | |
| state.resize = true | |
| state.wh = window.innerHeight | |
| this.setBounds() | |
| this.setElems() | |
| this.transformElems() | |
| this.clamp() | |
| state.scroll = state.current = state.target | |
| state.resize = false | |
| } | |
| run = () => { | |
| const state = this.state | |
| state.current += (state.target - state.current) * 0.1 | |
| state.scroll = Math.round(state.current * 100) / 100 | |
| !state.resize && this.transformElems() | |
| } | |
| scroll = ({ y }) => { | |
| this.state.target += y | |
| this.clamp() | |
| } | |
| clamp() { | |
| this.state.target = gsap.utils.clamp(0, this.state.max, this.state.target) | |
| } | |
| transformElems() { | |
| this.elems.forEach(elem => { | |
| const { visible, transform } = this.visible(elem) | |
| if (visible || this.state.resize) { | |
| elem.out && (elem.out = false) | |
| elem.el.style.transform = `translate3d(${-transform}px, 0, 0)` | |
| } else if (!elem.out) { | |
| elem.out = true | |
| elem.el.style.transform = `translate3d(${-transform}px, 0, 0)` | |
| } | |
| }) | |
| } | |
| visible({ start, end, speed }) { | |
| const transform = this.state.scroll * speed | |
| const visible = (transform > start) && (transform < end) | |
| return { | |
| transform, | |
| visible | |
| } | |
| } | |
| removeEvents() { | |
| Events.off('scroll', this.scroll) | |
| Events.off('tick', this.run) | |
| Events.off('resize', this.resize) | |
| } | |
| destroy() { | |
| this.removeEvents() | |
| this.ui = null | |
| this.state = null | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment