UNPKG

baseframe-js

Version:

Baseframe JS is a comprehensive suite of modular plugins and utilities designed for front-end development

40 lines (39 loc) 1.63 kB
import $be from 'base-elem-js'; import { body, isFunc } from '../util/helpers'; import animate from '../util/animate'; import debounce from './debounce'; import Easing from '../util/Easing'; const EVENT_NAME = 'smoothScroll'; const userBreakEvents = [`wheel.${EVENT_NAME}`, `touchstart.${EVENT_NAME}`]; let activeScroll = false; export default function smoothScroll(scrollTargetY, duration = 500, easing = 'easeOutQuint', scrollEndFn) { if (activeScroll) return; let progress = 0; const startScrollY = window.scrollY, scrollDistance = Math.abs(startScrollY - scrollTargetY), scrollDir = startScrollY < scrollTargetY ? 1 : -1, msPerFrame = 1000 / 60, frames = duration / msPerFrame, progressSize = scrollDistance / frames; if (scrollDistance === 0) return; activeScroll = true; body.style.scrollBehavior = 'auto'; const easingFn = isFunc(easing) ? easing : Easing[easing]; const cancelAnimation = animate(() => { progress += progressSize; const scrollProgress = scrollDistance * easingFn(progress / scrollDistance); const yPos = startScrollY + scrollProgress * scrollDir; window.scroll(0, yPos); if (progress > scrollDistance) cancel(); }); const cancel = () => { if (isFunc(scrollEndFn)) scrollEndFn(); cancelAnimation(); $be(window).off([...userBreakEvents, `scroll.${EVENT_NAME}`]); body.style.scrollBehavior = null; activeScroll = false; }; $be(window).on(userBreakEvents, cancel); debounce(window, `scroll.${EVENT_NAME}`, cancel); }