102 lines
4.1 KiB
JavaScript
102 lines
4.1 KiB
JavaScript
|
export default defineNuxtPlugin((NuxtApp) => {
|
||
|
|
||
|
NuxtApp.vueApp.directive('animate', (el, binding) => {
|
||
|
el.classList.add('animate')
|
||
|
|
||
|
el.setAttribute('data-animate-duration', binding.value.duration || 250 )
|
||
|
el.setAttribute('data-animate-delay', binding.value.delay || 200 )
|
||
|
el.setAttribute('data-animate-preset', binding.value.preset || 'fade' )
|
||
|
el.setAttribute('data-animate-stagger', binding.value.stagger || false )
|
||
|
el.setAttribute('data-animate-stagger-delay', binding.value.staggerDelay || 100 )
|
||
|
})
|
||
|
|
||
|
NuxtApp.hook('page:finish', () => {
|
||
|
const applyClasses = (el, type) => {
|
||
|
const initialClasses = JSON.parse(el.getAttribute('data-animate-initial'))
|
||
|
const animateClasses = JSON.parse(el.getAttribute('data-animate-animate'))
|
||
|
|
||
|
if (type === 'initial') {
|
||
|
Object.keys(initialClasses).forEach(x => {
|
||
|
el.style[x] = initialClasses[x]
|
||
|
})
|
||
|
|
||
|
el.style['transition-property'] = 'none'
|
||
|
}
|
||
|
|
||
|
if (type === 'animate') {
|
||
|
Object.keys(animateClasses).forEach(x => {
|
||
|
el.style[x] = animateClasses[x]
|
||
|
})
|
||
|
|
||
|
el.style['transition-property'] = 'all'
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const callback = (entries) => {
|
||
|
entries.forEach(entry => {
|
||
|
if (entry.isIntersecting) {
|
||
|
applyClasses(entry.target, 'animate')
|
||
|
} else {
|
||
|
applyClasses(entry.target, 'initial')
|
||
|
}
|
||
|
})
|
||
|
}
|
||
|
|
||
|
// Configure staggering animations
|
||
|
let targets = document.querySelectorAll('.animate')
|
||
|
targets.forEach((target) => {
|
||
|
if (target.getAttribute('data-animate-stagger') === 'true') {
|
||
|
target.classList.remove('animate')
|
||
|
|
||
|
const collection = target.children
|
||
|
Object.values(collection).forEach((child, index) => {
|
||
|
child.setAttribute('data-animate-preset', target.getAttribute('data-animate-preset') )
|
||
|
child.setAttribute('data-animate-duration', target.getAttribute('data-animate-duration') )
|
||
|
|
||
|
child.style.transitionDelay = Number(target.getAttribute('data-animate-delay')) + index * Number(target.getAttribute('data-animate-stagger-delay')) + 'ms'
|
||
|
child.classList.add('animate')
|
||
|
})
|
||
|
} else {
|
||
|
target.style.transitionDelay = target.getAttribute('data-animate-delay') + 'ms'
|
||
|
}
|
||
|
})
|
||
|
|
||
|
|
||
|
// Configure presets
|
||
|
const observer = new IntersectionObserver(callback)
|
||
|
targets = document.querySelectorAll('.animate')
|
||
|
|
||
|
targets.forEach(target => {
|
||
|
const preset = target.getAttribute('data-animate-preset')
|
||
|
|
||
|
if (preset === 'fade') {
|
||
|
target.setAttribute('data-animate-initial', JSON.stringify({ opacity: 0 }))
|
||
|
target.setAttribute('data-animate-animate', JSON.stringify({ opacity: 100 }))
|
||
|
|
||
|
} else if (preset === 'slide-left') {
|
||
|
target.setAttribute('data-animate-initial', JSON.stringify({ opacity: 0, transform: 'translateX(-6em)', filter: 'blur(5px)' }))
|
||
|
target.setAttribute('data-animate-animate', JSON.stringify({ opacity: 100, transform: 'translateX(0)', filter: 'blur(0)' }))
|
||
|
|
||
|
} else if (preset === 'slide-right') {
|
||
|
target.setAttribute('data-animate-initial', JSON.stringify({ opacity: 0, transform: 'translateX(6em)', filter: 'blur(5px)' }))
|
||
|
target.setAttribute('data-animate-animate', JSON.stringify({ opacity: 100, transform: 'translateX(0)', filter: 'blur(0px)' }))
|
||
|
|
||
|
} else if (preset === 'slide-up') {
|
||
|
target.setAttribute('data-animate-initial', JSON.stringify({ opacity: 0, transform: 'translateY(-2em)', filter: 'blur(5px)' }))
|
||
|
target.setAttribute('data-animate-animate', JSON.stringify({ opacity: 100, transform: 'translateY(0)', filter: 'blur(0px)' }))
|
||
|
|
||
|
} else if (preset === 'slide-down') {
|
||
|
target.setAttribute('data-animate-initial', JSON.stringify({ opacity: 0, transform: 'translateY(2em)', filter: 'blur(5px)' }))
|
||
|
target.setAttribute('data-animate-animate', JSON.stringify({ opacity: 100, transform: 'translateY(0)', filter: 'blur(0px)' }))
|
||
|
}
|
||
|
|
||
|
applyClasses(target, 'initial')
|
||
|
|
||
|
target.classList.add('transition-all')
|
||
|
target.style['transition-duration'] = target.getAttribute('data-animate-duration') + 'ms'
|
||
|
|
||
|
observer.observe(target)
|
||
|
})
|
||
|
})
|
||
|
})
|