From 4cf75125e6b9014360955d7888f7f2e6e5d1c06f Mon Sep 17 00:00:00 2001 From: Aaron Chan <42254254+aaronchan32@users.noreply.github.com> Date: Thu, 4 Apr 2024 19:03:50 -0700 Subject: [PATCH] feat: add logo and register button animation on scroll --- src/App.tsx | 14 ++- .../LogoAndRegister/LogoAndRegister.scss | 42 +++++++++ .../LogoAndRegister/LogoAndRegister.tsx | 86 +++++++++++++++++++ src/pages/Home/Home.scss | 24 +++--- src/pages/Home/Home.tsx | 16 ++-- src/pages/Timeline/Timeline.scss | 1 - 6 files changed, 164 insertions(+), 19 deletions(-) create mode 100644 src/components/LogoAndRegister/LogoAndRegister.scss create mode 100644 src/components/LogoAndRegister/LogoAndRegister.tsx diff --git a/src/App.tsx b/src/App.tsx index a9b9c2f..3bbe434 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -9,6 +9,7 @@ import FAQ from './pages/FAQ/FAQ'; import Timeline from './pages/Timeline/Timeline'; import Judges from './pages/Judges/Judges'; import { useRef } from 'react'; +import LogoAndRegister from './components/LogoAndRegister/LogoAndRegister'; function Rotate() { const scrollContainerRef = useRef(null); @@ -17,6 +18,8 @@ function Rotate() { const scroll3Ref = useRef(null); const scroll4Ref = useRef(null); const planetRef = useRef(null); + const fakeLogoRef = useRef(null); + const fakeRegisterRef = useRef(null); const scrollRefList = [scroll1Ref, scroll2Ref, scroll3Ref, scroll4Ref]; @@ -31,7 +34,16 @@ function Rotate() { scrollRefList={scrollRefList} scrollContainerRef={scrollContainerRef} /> - + + diff --git a/src/components/LogoAndRegister/LogoAndRegister.scss b/src/components/LogoAndRegister/LogoAndRegister.scss new file mode 100644 index 0000000..d755351 --- /dev/null +++ b/src/components/LogoAndRegister/LogoAndRegister.scss @@ -0,0 +1,42 @@ +.logo-and-register { + @media (max-width: $mobile-breakpoint) { + display: none; + } + + img { + position: fixed; + opacity: 0; + pointer-events: none; + z-index: 1; + } + + .register-button { + position: fixed; + opacity: 0; + z-index: 5; + .button { + background: $primary-orange; + display: inline-block; + font-size: 1.5em; + padding: 0.5em 1.2em; + text-decoration: none; + color: $primary-white; + letter-spacing: 2.4px; + } + + .parallelogram { + transform: skew(-15deg); + } + + .skew-fix { + display: inline-block; + transform: skew(15deg); + } + + @media screen and (max-width: $mobile-breakpoint) { + display: block; + margin: 0 auto 2rem; + width: 100%; + } + } +} diff --git a/src/components/LogoAndRegister/LogoAndRegister.tsx b/src/components/LogoAndRegister/LogoAndRegister.tsx new file mode 100644 index 0000000..cb90f5c --- /dev/null +++ b/src/components/LogoAndRegister/LogoAndRegister.tsx @@ -0,0 +1,86 @@ +import './LogoAndRegister.scss'; +import { useEffect, useRef } from 'react'; +import Logo from '/Logo.svg'; + +type LogoAndRegisterProps = { + scrollContainerRef: React.RefObject; + fakeLogoRef: React.RefObject; + fakeRegisterRef: React.RefObject; +}; + +export default function LogoAndRegister({ + scrollContainerRef, + fakeLogoRef, + fakeRegisterRef +}: LogoAndRegisterProps) { + const logoRef = useRef(null); + const registerRef = useRef(null); + + useEffect(() => { + const fakeLogoInfo = fakeLogoRef.current?.getBoundingClientRect(); + const logoInfo = logoRef.current?.getBoundingClientRect(); + const initialLogoWidth = parseInt(logoInfo!.width); + // Change to ref in the future + const navigationElement = document.querySelector('nav'); + const navRightValue = parseInt( + window.getComputedStyle(navigationElement).getPropertyValue('right') + ); + + const fakeRegisterInfo = fakeRegisterRef.current?.getBoundingClientRect(); + const registerInfo = registerRef.current?.getBoundingClientRect(); + const initialRegisterWidth = parseInt(registerInfo!.width); + + if (logoRef.current && fakeLogoInfo) { + logoRef.current.style.transform = `translate(${fakeLogoInfo.x}px, ${fakeLogoInfo.y - 10}px)`; + logoRef.current.style.opacity = '1'; + setTimeout(() => { + (logoRef.current!.style.transition = + 'transform 0.4s ease-out, scale 0.4s ease-out'), + 0; + }); + } + + if (registerRef.current && fakeRegisterInfo) { + registerRef.current.style.transform = `translate(${fakeRegisterInfo.x}px, ${fakeRegisterInfo.y}px)`; + registerRef.current.style.opacity = '1'; + setTimeout(() => { + (registerRef.current!.style.transition = 'transform 0.4s ease-out'), 0; + }); + } + + const lastScrollTop = 0; + if (scrollContainerRef.current && logoRef.current) { + scrollContainerRef.current.addEventListener('scroll', () => { + const st = scrollContainerRef.current!.scrollTop; + if (st > lastScrollTop && st > window.innerHeight / 2) { + // downscroll code + const scaleFactor = 0.5; + console.log(window.innerWidth); + logoRef.current!.style.transform = `translate(${window.innerWidth - (initialLogoWidth * scaleFactor * 1.5 + navRightValue)}px, 50px) scale(${scaleFactor})`; + + registerRef.current!.style.transform = `translate(${window.innerWidth - (initialRegisterWidth + navRightValue)}px, ${window.innerHeight - (registerInfo!.height + 50)}px)`; + } else { + // upscroll code + logoRef.current!.style.scale = '1'; + if (fakeLogoInfo) { + logoRef.current!.style.transform = `translate(${fakeLogoInfo?.x}px, ${fakeLogoInfo?.y - 10}px)`; + } + if (fakeRegisterInfo) { + registerRef.current!.style.transform = `translate(${fakeRegisterInfo?.x}px, ${fakeRegisterInfo?.y}px)`; + } + } + }); + } + }, [fakeLogoRef, scrollContainerRef, fakeRegisterRef]); + + return ( + + ); +} diff --git a/src/pages/Home/Home.scss b/src/pages/Home/Home.scss index e18624a..b9d5743 100644 --- a/src/pages/Home/Home.scss +++ b/src/pages/Home/Home.scss @@ -60,26 +60,28 @@ @media (max-width: 550px) { width: 100%; } - } - .logo { - @media screen and (max-width: $mobile-breakpoint) { - display: none; + .fake-logo { + opacity: 0; + @media screen and (max-width: $mobile-breakpoint) { + display: none; + } } - } - .mobile-logo { - display: none; + .mobile-logo { + display: none; - @media screen and (max-width: $mobile-breakpoint) { - display: block; - margin: 0 auto 1rem; - position: relative; + @media screen and (max-width: $mobile-breakpoint) { + display: block; + margin: 0 auto 1rem; + position: relative; + } } } /* REGISTER BUTTON */ .register-button { + opacity: 0; .button { background: $primary-orange; display: inline-block; diff --git a/src/pages/Home/Home.tsx b/src/pages/Home/Home.tsx index 0c21ffc..3625f96 100644 --- a/src/pages/Home/Home.tsx +++ b/src/pages/Home/Home.tsx @@ -6,11 +6,15 @@ import { useRef } from 'react'; type HomeProps = { scroll1Ref: React.RefObject; + fakeLogoRef: React.RefObject; + fakeRegisterRef: React.RefObject; }; -export default function Home({ scroll1Ref }: HomeProps) { - const registerRef = useRef(null); - const logoRef = useRef(null); +export default function Home({ + scroll1Ref, + fakeLogoRef, + fakeRegisterRef +}: HomeProps) { const mobileDateRef = useRef(null); return ( @@ -20,9 +24,9 @@ export default function Home({ scroll1Ref }: HomeProps) {
Design Frontiers Logo @@ -45,7 +49,7 @@ export default function Home({ scroll1Ref }: HomeProps) {

DIB ROOM 208

-
+
REGISTER NOW diff --git a/src/pages/Timeline/Timeline.scss b/src/pages/Timeline/Timeline.scss index f3c177e..031e659 100644 --- a/src/pages/Timeline/Timeline.scss +++ b/src/pages/Timeline/Timeline.scss @@ -71,7 +71,6 @@ display: flex; flex-direction: column; justify-content: space-between; - width: 50vw; @media screen and (max-width: $mobile-breakpoint) { width: 72vw;