123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- import BezierEasing from 'bezier-easing'
- let _ = {
- $ (selector) {
- return document.querySelector(selector)
- },
- on (element, events, handler) {
- if (!(events instanceof Array)) {
- events = [events]
- }
- for (let i = 0; i < events.length; i++) {
- element.addEventListener(events[i], handler)
- }
- },
- off (element, events, handler) {
- if (!(events instanceof Array)) {
- events = [events]
- }
- for (let i = 0; i < events.length; i++) {
- element.removeEventListener(events[i], handler)
- }
- }
- }
- let eases = {
- ease: [0.25, 0.1, 0.25, 1.0],
- linear: [0.00, 0.0, 1.00, 1.0],
- 'ease-in': [0.42, 0.0, 1.00, 1.0],
- 'ease-out': [0.00, 0.0, 0.58, 1.0],
- 'ease-in-out': [0.42, 0.0, 0.58, 1.0]
- }
- export const scrollTo = (element, duration = 500, options) => {
- options = options || {}
- options.easing = eases[options.easing || 'ease']
- if (typeof element === 'string') {
- element = _.$(element)
- }
- let page = _.$('html, body')
- let events = [
- 'scroll',
- 'mousedown',
- 'wheel',
- 'DOMMouseScroll',
- 'mousewheel',
- 'keyup',
- 'touchmove'
- ]
- let abort = false
- let abortFn = () => {
- abort = true
- }
- _.on(page, events, abortFn)
- let initialY = window.pageYOffset
- let elementY = 0
- if (Object.is(typeof element, 'number')) {
- elementY = element
- } else {
- elementY = initialY + element.getBoundingClientRect().top + (options.offset || 0)
- }
- let targetY = document.body.scrollHeight - elementY < window.innerHeight
- ? document.body.scrollHeight - window.innerHeight
- : elementY
- if (options.offset) {
- targetY += options.offset
- }
- let diff = targetY - initialY
- let easing = BezierEasing.apply(BezierEasing, options.easing)
- let start
- let done = () => {
- _.off(page, events, abortFn)
- if (abort && options.onCancel) options.onCancel()
- if (!abort && options.onDone) options.onDone()
- }
- if (!diff) return
- window.requestAnimationFrame(function step (timestamp) {
- if (abort) return done()
- if (!start) start = timestamp
- let time = timestamp - start
- let progress = Math.min(time / duration, 1)
- progress = easing(progress)
- window.scrollTo(0, initialY + diff * progress)
- if (time < duration) {
- window.requestAnimationFrame(step)
- } else {
- done()
- }
- })
- }
|