Skip to content

Instantly share code, notes, and snippets.

@jesperlandberg
Created November 28, 2021 23:06
Show Gist options
  • Save jesperlandberg/e53dff30d52edb45f0ec7330c588d916 to your computer and use it in GitHub Desktop.
Save jesperlandberg/e53dff30d52edb45f0ec7330c588d916 to your computer and use it in GitHub Desktop.
import gsap from 'gsap'
import { evt, utils, store } from '@/core'
const { qs, qsa, rect } = utils
const { bounds, flags } = store
export default function (elems = qsa('[data-smooth-item]')) {
let scroll = 0
let isResizing = false
let cache = null
const total = elems.length - 1
function setSections() {
cache = elems.map((el, i) => {
gsap.set(el, { y: 0 })
const { top, bottom } = rect(el)
const start = top - bounds.wh
const end = bottom
const ySet = gsap.quickSetter(el, 'y', 'px')
i === total && (bounds.maxScroll = bottom - bounds.wh)
return { el, start, end, ySet, out: true }
})
}
function tick({ cY }) {
scroll = cY
!isResizing && transformSections()
}
function transformSections() {
if (flags.locked) return
cache.length &&
cache.forEach(c => {
const { start, end, ySet } = c
const isVisible = inView(start, end)
if (isVisible || isResizing) {
c.out && (c.out = false)
ySet(-scroll)
} else if (!c.out) {
c.out = true
ySet(-scroll)
}
})
}
function inView(start, end) {
return scroll > start && scroll < end
}
function resize() {
isResizing = true
setSections()
evt.emit('resize:on-reset')
transformSections()
isResizing = false
}
function mount() {
evt.on('tick', tick)
evt.on('resize resize:scroll', resize)
}
function unmount() {
evt.off('tick', tick)
evt.off('resize resize:scroll', resize)
cache = null
evt.emit('scroll:on-reset')
}
setSections()
mount()
return {
unmount
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment