45 lines
1.2 KiB
TypeScript
45 lines
1.2 KiB
TypeScript
import { animate, inView, stagger } from 'motion'
|
|
import { quartOut } from '$animations/easings'
|
|
|
|
const defaultOptions = {
|
|
stagger: null,
|
|
delay: 0,
|
|
duration: 1.6,
|
|
easing: quartOut,
|
|
}
|
|
|
|
export default (node: Element | any, {
|
|
enable = true,
|
|
children = undefined,
|
|
animation = [],
|
|
options = defaultOptions,
|
|
}: RevealOptions) => {
|
|
if (!enable) return
|
|
|
|
// Define targets from children, if empty get node
|
|
const targets = children ? node.querySelectorAll(children) : [node]
|
|
|
|
// If animation has opacity starting with 0, hide it first
|
|
if (animation.opacity && animation.opacity[0] === 0) {
|
|
targets.forEach((el: HTMLElement) => el.style.opacity = '0')
|
|
}
|
|
|
|
// Create inView instance
|
|
inView(node, ({ isIntersecting }) => {
|
|
const anim = animate(
|
|
targets,
|
|
animation,
|
|
{
|
|
delay: options.stagger ? stagger(options.stagger, { start: options.delay }) : options.delay,
|
|
duration: options.duration,
|
|
easing: options.easing,
|
|
}
|
|
)
|
|
anim.stop()
|
|
|
|
// Run animation if in view and tab is active
|
|
isIntersecting && requestAnimationFrame(anim.play)
|
|
}, {
|
|
amount: options.threshold,
|
|
})
|
|
} |