UNPKG

vuetify

Version:

Vue.js 2 Semantic Component Framework

89 lines (72 loc) 2.68 kB
import * as easingPatterns from '../../../util/easing-patterns' const defaults = { duration: 500, offset: 0, easing: 'easeInOutCubic' } function getDocumentHeight () { return Math.max( document.body.scrollHeight, document.documentElement.scrollHeight, document.body.offsetHeight, document.documentElement.offsetHeight, document.body.clientHeight, document.documentElement.clientHeight ) } function getWindowHeight () { return window.innerHeight || (document.documentElement || document.body).clientHeight } function isVueComponent (obj) { return obj != null && obj._isVue } function getTargetLocation (target, settings) { let location if (isVueComponent(target)) { target = target.$el } if (target instanceof Element) { location = target.getBoundingClientRect().top + window.pageYOffset } else if (typeof target === 'string') { const targetEl = document.querySelector(target) if (!targetEl) throw new TypeError(`Target element "${target}" not found.`) location = targetEl.getBoundingClientRect().top + window.pageYOffset } else if (typeof target === 'number') { location = target } else { const type = target == null ? target : target.constructor.name throw new TypeError(`Target must be a Selector/Number/DOMElement/VueComponent, received ${type} instead.`) } return Math.round( Math.min( Math.max(location + settings.offset, 0), getDocumentHeight() - getWindowHeight() ) ) } export default function goTo (target, options) { return new Promise((resolve, reject) => { if (typeof window === 'undefined') return reject('Window is undefined') const settings = Object.assign({}, defaults, options) const startTime = performance.now() const startLocation = window.pageYOffset const targetLocation = getTargetLocation(target, settings) const distanceToScroll = targetLocation - startLocation const easingFunction = typeof settings.easing === 'function' ? settings.easing : easingPatterns[settings.easing] if (!easingFunction) throw new TypeError(`Easing function '${settings.easing}' not found.`) function step (currentTime) { const progressPercentage = Math.min(1, ((currentTime - startTime) / settings.duration)) const targetPosition = Math.floor(startLocation + distanceToScroll * easingFunction(progressPercentage)) window.scrollTo(0, targetPosition) if ( Math.round(window.pageYOffset) === targetLocation || progressPercentage === 1 ) { return resolve(target) } window.requestAnimationFrame(step) } window.requestAnimationFrame(step) }) }