193 lines
No EOL
5.5 KiB
TypeScript
193 lines
No EOL
5.5 KiB
TypeScript
import { goto } from '$app/navigation';
|
|
import gsap from 'gsap';
|
|
import SplitText from 'gsap/dist/SplitText';
|
|
import { workbulge } from '$lib/utils/stores';
|
|
|
|
const bulge = {factor: 0};
|
|
workbulge.subscribe(value => {
|
|
bulge.factor = value;
|
|
})
|
|
|
|
export function initWorkPage( canvasTextElems: Array<HTMLElement>, canvasImgElems: Array<HTMLElement>) {
|
|
|
|
workbulge.set(0);
|
|
|
|
gsap.to(bulge, {
|
|
duration: .5,
|
|
factor: 0.15,
|
|
delay: .8,
|
|
ease: 'back.out(3)',
|
|
onUpdate: () => {
|
|
workbulge.set(bulge.factor);
|
|
}
|
|
})
|
|
|
|
const workinfos: Array<HTMLElement> = Array.from(document.querySelectorAll('.work-info'));
|
|
|
|
workinfos.forEach((workinfo) => {
|
|
|
|
const workinfoTitle = workinfo.querySelector('h2') as HTMLElement;
|
|
const workinfoTitleWords = workinfoTitle.querySelector('span') as HTMLElement;
|
|
|
|
const expanded = {
|
|
height: workinfo.getBoundingClientRect().height,
|
|
width: workinfo.getBoundingClientRect().width + 2,
|
|
paddingTop: Number(window.getComputedStyle(workinfo).paddingTop.replace('px','')) as number,
|
|
paddingLeft: Number(window.getComputedStyle(workinfo).paddingLeft.replace('px','')) as number,
|
|
}
|
|
|
|
const contracted = {
|
|
height: workinfoTitle.offsetHeight * 1.2 + 2 * expanded.paddingTop,
|
|
width: workinfoTitleWords.offsetWidth + 2 * expanded.paddingLeft,
|
|
}
|
|
|
|
workinfo.style.width = `${contracted.width}px`;
|
|
workinfo.style.height = `${contracted.height}px`;
|
|
const tags = workinfo.querySelector('.tags') as HTMLElement;
|
|
tags.style.width = `${expanded.width}px`;
|
|
|
|
workinfo.parentElement?.addEventListener('mouseenter', () => {
|
|
gsap.to(workinfo, {
|
|
duration: .25,
|
|
width: expanded.width,
|
|
height: expanded.height,
|
|
ease: 'power2.inOut',
|
|
overwrite: true
|
|
})
|
|
}, { passive: true })
|
|
workinfo.parentElement?.addEventListener('mouseleave', () => {
|
|
gsap.to(workinfo, {
|
|
duration: .25,
|
|
width: contracted.width,
|
|
height: contracted.height,
|
|
ease: 'power2.inOut',
|
|
overwrite: true
|
|
})
|
|
}, { passive: true })
|
|
})
|
|
|
|
gsap.registerPlugin( SplitText );
|
|
|
|
const work = document.querySelectorAll('.work');
|
|
gsap.set(document.querySelectorAll('.tag'), {opacity: 0, yPercent: 200});
|
|
gsap.set(document.querySelectorAll('h2'), {opacity: 1 });
|
|
work.forEach((el) => {
|
|
el.addEventListener('mouseenter', (e) => {
|
|
const target = e.target as HTMLElement;
|
|
gsap.to(target?.querySelectorAll('.tag'), {duration: 0.5, opacity: 1, yPercent: 0, ease: 'back.out(1.7)', stagger: 0.025, overwrite: true});
|
|
gsap.to(target?.querySelector('h2'), {duration: 0.5, opacity: 1, ease: 'back.out(1.7)', overwrite: true});
|
|
}, { passive: true });
|
|
el.addEventListener('mouseleave', (e) => {
|
|
const target = e.target as HTMLElement;
|
|
gsap.to(target?.querySelectorAll('.tag'), {duration: 0.3, opacity: 0, yPercent: 200, ease: 'power2.out', overwrite: true});
|
|
gsap.to(target?.querySelector('h2'), {duration: 0.5, opacity: 1, ease: 'back.out(1.7)', overwrite: true});
|
|
}, { passive: true });
|
|
});
|
|
|
|
gsap.set('.work', {
|
|
opacity: 0, yPercent: 50
|
|
})
|
|
|
|
gsap.to('.work', {
|
|
duration: 1,
|
|
opacity: 1,
|
|
yPercent: 0,
|
|
stagger: 0.05,
|
|
ease: 'elastic.out(0.75, 0.5)',
|
|
delay: 0.3,
|
|
})
|
|
|
|
return {
|
|
text: canvasTextElems,
|
|
images: canvasImgElems
|
|
}
|
|
}
|
|
|
|
export function workClickHandler(e:Event){
|
|
e.preventDefault();
|
|
const target = e.target as HTMLElement;
|
|
const originalLink = target.getAttribute('href') as string;
|
|
const targetImg = target.querySelector('img') as HTMLElement;
|
|
const targetImgRect = targetImg.getBoundingClientRect();
|
|
const targetImgAspectRatio = targetImgRect.width / targetImgRect.height;
|
|
target.classList.add('active');
|
|
targetImg.style.width = `${targetImgRect.width}px`;
|
|
targetImg.style.height = `${targetImgRect.height}px`;
|
|
targetImg.style.top = `${targetImgRect.top}px`;
|
|
targetImg.style.left = `${targetImgRect.left}px`;
|
|
const clone = targetImg.cloneNode(true) as HTMLElement;
|
|
targetImg.parentElement?.insertBefore(clone, targetImg);
|
|
targetImg.style.position = 'fixed';
|
|
const coverclone = targetImg.cloneNode(true) as HTMLElement;
|
|
coverclone.classList.add('coverclone');
|
|
coverclone.style.zIndex = '-1';
|
|
coverclone.style.visibility = 'visible';
|
|
coverclone.style.opacity = '0';
|
|
|
|
document.body.appendChild(coverclone);
|
|
|
|
gsap.to('.work .work-info', {
|
|
duration: .3,
|
|
opacity: 0,
|
|
yPercent: -10,
|
|
ease: 'power4.out',
|
|
})
|
|
gsap.to('.work:not(.active) img', {
|
|
duration: .3,
|
|
opacity: 0,
|
|
yPercent: 20,
|
|
ease: 'power4.out',
|
|
})
|
|
gsap.to('.work h2', {
|
|
duration: .3,
|
|
opacity: 0,
|
|
// scale: 0,
|
|
ease: 'power3.out'
|
|
})
|
|
gsap.to('.work .tag', {
|
|
duration: .3,
|
|
opacity: 0,
|
|
// scale: 0,
|
|
ease: 'power3.out'
|
|
})
|
|
gsap.set(targetImg, {
|
|
zIndex: 100,
|
|
})
|
|
gsap.to(coverclone, {
|
|
duration: .3,
|
|
top: 0,
|
|
left: 0,
|
|
opacity: 1,
|
|
width: window.innerWidth,
|
|
height: window.innerWidth / targetImgAspectRatio,
|
|
ease: 'circ.inOut',
|
|
delay: 0.3
|
|
})
|
|
gsap.to(targetImg, {
|
|
duration: .3,
|
|
top: 0,
|
|
left: 0,
|
|
width: window.innerWidth,
|
|
height: window.innerWidth / targetImgAspectRatio,
|
|
ease: 'circ.inOut',
|
|
delay: 0.3
|
|
})
|
|
gsap.to(bulge, {
|
|
duration: .3,
|
|
factor: 0,
|
|
ease: 'circ.inOut',
|
|
onUpdate: () => {
|
|
workbulge.set(bulge.factor);
|
|
}
|
|
})
|
|
gsap.to('h1 span', {
|
|
duration: .3,
|
|
yPercent: -100,
|
|
opacity: 0,
|
|
ease: 'circ.inOut',
|
|
})
|
|
|
|
setTimeout(() => {
|
|
goto(originalLink);
|
|
}, 600);
|
|
} |