UNPKG

wotsui-vue-directives

Version:
153 lines (152 loc) 5.31 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const intersection_1 = require("../hooks/intersection"); const baseAnimation = { delay: 100, direction: 'normal', duration: 250, fillMode: 'both', iterationCount: 1, name: 'fade', timingFunction: 'ease', }; const baseSettings = { ...intersection_1.intersectionSettings, target: 'self', queue: false, interval: 100, animations: [{ ...baseAnimation }], }; function animateOnScroll(el, binding) { const settings = initSettings(binding); const observer = new IntersectionObserver(handleIntersection, { threshold: settings.treshold, }); intersection_1.setIntersectionClasses(el, settings, false); bindsMap.set(el, settings); observer.observe(el); } exports.default = animateOnScroll; function initSettings(binding) { const settings = { ...baseSettings }; if (binding.modifiers.children) settings.target = 'children'; if (binding.modifiers.queue) settings.queue = true; if (typeof binding.value === 'object' && binding.value.animations) { Object.assign(settings, binding.value); settings.animations = getAnimationsObjects(binding.value.animations); } else { settings.animations = getAnimationsObjects(binding.value); } return settings; } function getAnimationsObjects(value) { const animationsObjects = []; if (Array.isArray(value)) { value.forEach((val) => { animationsObjects.push(createAnimationObject(val)); }); } else { animationsObjects.push(createAnimationObject(value)); } return animationsObjects; } function createAnimationObject(value) { const animationObject = { ...baseAnimation }; if (typeof value === 'number') animationObject.duration = value; if (typeof value === 'object') Object.assign(animationObject, value); if (typeof value === 'string') animationObject.name = value; return animationObject; } function handleIntersection(entries, observer) { entries.forEach((entry) => { if (entry.isIntersecting) { const el = entry.target; const settings = bindsMap.get(el); if (!settings) { observer.unobserve(el); return; } intersection_1.setIntersectionClasses(el, settings, true); el.dispatchEvent(new CustomEvent('animation-start')); setAnimations(el, settings); const estimatedTime = getEstimatedTime(el, settings); setTimeout(() => { if (el) { el.dispatchEvent(new CustomEvent('animation-end')); } }, estimatedTime); bindsMap.delete(el); observer.unobserve(el); } }); } function setAnimations(el, settings) { if (settings.target === 'self') { const animationString = getAnimationString(settings.animations, 0); el.style.animation = animationString; } if (settings.target === 'children') { const { children } = el; for (let i = 0; i < children.length; i++) { const child = children[i]; const delay = settings.queue ? i * +parseTime(settings.interval) : 0; const animationString = getAnimationString(settings.animations, delay); child.style.animation = animationString; } } } function getAnimationString(animationObjects, extraDelay = 0) { const animations = []; animationObjects.forEach((aniObj) => { const aniProps = []; const delay = +parseTime(aniObj.delay) + +parseTime(extraDelay); aniProps.push(aniObj.name); aniProps.push(parseTime(aniObj.duration, true)); aniProps.push(`${delay / 1000}s`); aniProps.push(aniObj.direction); aniProps.push(aniObj.fillMode); aniProps.push(aniObj.iterationCount.toString()); aniProps.push(aniObj.timingFunction); animations.push(aniProps.join(' ')); }); return animations.join(', '); } function getEstimatedTime(el, settings) { let delay = +parseTime(settings.animations[0].delay); let duration = +parseTime(settings.animations[0].duration); for (const animation of settings.animations) { const _delay = +parseTime(animation.delay); const _duration = +parseTime(animation.duration); if (_delay > delay) delay = _delay; if (_duration > duration) duration = _duration; } let time = delay + duration; if (settings.target === 'children' && settings.queue) { const { length: n } = el.children; time += +parseTime(settings.interval) * (n - 1); } return time; } function parseTime(value, toString = false) { let parsedTime = 0; if (typeof value === 'number') { parsedTime = value; } if (typeof value === 'string') { parsedTime = parseFloat(value.replace(/\D/g, '')) * 1000; } if (toString) { return `${parsedTime / 1000}s`; } return parsedTime; } const bindsMap = new Map();