Skip to content

Instantly share code, notes, and snippets.

@jesperlandberg
Last active November 28, 2021 18:43
Show Gist options
  • Save jesperlandberg/d5043340fd2b7bde824e1e04670356c9 to your computer and use it in GitHub Desktop.
Save jesperlandberg/d5043340fd2b7bde824e1e04670356c9 to your computer and use it in GitHub Desktop.
import gsap from 'gsap'
import { evt, utils } from '@/core'
const { qs, qsa, rect } = utils
export default function () {
const el = qs('.js-clip-menu')
const mask = qs('.js-clip-menu-mask', el)
const items = qsa('.js-clip-menu-link', el)
const clip = {
left: 0,
right: 0,
}
const tl = gsap.timeline({
paused: true,
onUpdate: () => gsap.set(mask, {
clipPath: `inset(3px ${clip.right}px 3px ${clip.left}px round 999px)`,
})
})
let lastIdx = 0
let currentIdx = 0
let maskBounds
let cache
function resize() {
maskBounds = rect(mask)
cache = items.map(item => {
const { left, width } = rect(item)
const cl = left - maskBounds.left
const cr = (maskBounds.left + maskBounds.width) - (left + width)
return { cl, cr }
})
}
function onClick({ currentTarget }) {
lastIdx = currentIdx
currentIdx = items.indexOf(currentTarget)
const { cl, cr } = cache[currentIdx]
const duration = lastIdx >= currentIdx ? [.75, .85] : [.85, .75]
tl.clear()
.to(clip, {
left: cl,
duration: duration[0],
ease: 'power2.inOut'
})
.to(clip, {
right: cr,
duration: duration[1],
ease: 'power2.inOut'
}, 0)
.restart()
}
function mount() {
evt.on('click', items, onClick)
evt.on('resize:on-reset', resize)
}
function unmount() {
evt.off('click', items, onClick)
evt.off('resize:on-reset', resize)
}
resize()
mount()
return {
unmount
}
}
<header class="menu px-[3px] fixed bottom-[3rem] left-1/2 transform -translate-x-1/2 bg-white rounded-full overflow-hidden z-[1000] js-clip-menu">
<div class="relative">
<ul class="flex text-black">
<li>
<a href="/" class="cursor-pointer flex items-center px-[20px] pb-[2px] text-[14px] h-[50px] leading-none js-clip-menu-link">Home</a>
</li>
<li>
<a href="/work" class="cursor-pointer flex items-center px-[20px] pb-[2px] text-[14px] h-[50px] leading-none js-clip-menu-link">Work</a>
</li>
<li>
<a href="/" class="cursor-pointer flex items-center px-[20px] pb-[2px] text-[14px] h-[50px] leading-none js-clip-menu-link">Archive</a>
</li>
<li>
<a href="/" class="cursor-pointer flex items-center px-[20px] pb-[2px] text-[14px] h-[50px] leading-none js-clip-menu-link">About</a>
</li>
</ul>
<div class="menu-mask flex absolute inset-0 pointer-events-none z-2 bg-black text-white js-clip-menu-mask" aria-hidden="true">
<div class="flex items-center px-[20px] pb-[2px] text-[14px] h-[50px] leading-none">Home</div>
<div class="flex items-center px-[20px] pb-[2px] text-[14px] h-[50px] leading-none">Work</div>
<div class="flex items-center px-[20px] pb-[2px] text-[14px] h-[50px] leading-none">Archive</div>
<div class="flex items-center px-[20px] pb-[2px] text-[14px] h-[50px] leading-none">About</div>
</div>
</div>
</header>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment