diff --git a/next.config.mjs b/next.config.mjs index 4678774..b32ab76 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -1,4 +1,40 @@ /** @type {import('next').NextConfig} */ -const nextConfig = {}; +const nextConfig = { + async headers() { + return [ + { + source: '/:path*', + headers: [ + { + key: 'Cache-Control', + value: 'public, max-age=31536000, immutable', + }, + ], + }, + ]; + }, + images: { + remotePatterns: [ + { + protocol: 'https', + hostname: 'letsenhance.io', + port: '', + pathname: '/static/**', + }, + { + protocol: 'https', + hostname: 'encrypted-tbn0.gstatic.com', + port: '', + pathname: '/images/**', + }, + { + protocol: 'https', + hostname: 'labs.sigma.software', + port: '', + pathname: '/investment/**', + }, + ], + }, +}; export default nextConfig; diff --git a/package.json b/package.json index 247548c..d2466ae 100644 --- a/package.json +++ b/package.json @@ -19,13 +19,17 @@ "@react-three/fiber": "^8.16.8", "@types/three": "^0.165.0", "aos": "^2.3.4", + "clsx": "^2.1.1", + "framer-motion": "^11.11.11", "gsap": "^3.12.5", "lenis": "^1.1.6", "next": "14.2.3", "react": "^18", "react-dom": "^18", "react-fast-marquee": "^1.6.4", - "three": "^0.165.0" + "tailwind-merge": "^2.5.4", + "three": "^0.165.0", + "zustand": "^5.0.1" }, "devDependencies": { "@types/aos": "^3.0.7", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3c27266..12e5e07 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,6 +23,12 @@ importers: aos: specifier: ^2.3.4 version: 2.3.4 + clsx: + specifier: ^2.1.1 + version: 2.1.1 + framer-motion: + specifier: ^11.11.11 + version: 11.11.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1) gsap: specifier: ^3.12.5 version: 3.12.5 @@ -41,9 +47,15 @@ importers: react-fast-marquee: specifier: ^1.6.4 version: 1.6.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + tailwind-merge: + specifier: ^2.5.4 + version: 2.5.4 three: specifier: ^0.165.0 version: 0.165.0 + zustand: + specifier: ^5.0.1 + version: 5.0.1(@types/react@18.3.3)(react@18.3.1)(use-sync-external-store@1.2.0(react@18.3.1)) devDependencies: '@types/aos': specifier: ^3.0.7 @@ -566,6 +578,10 @@ packages: client-only@0.0.1: resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -874,6 +890,20 @@ packages: resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} engines: {node: '>=14'} + framer-motion@11.11.11: + resolution: {integrity: sha512-tuDH23ptJAKUHGydJQII9PhABNJBpB+z0P1bmgKK9QFIssHGlfPd6kxMq00LSKwE27WFsb2z0ovY0bpUyMvfRw==} + peerDependencies: + '@emotion/is-prop-valid': '*' + react: ^18.0.0 + react-dom: ^18.0.0 + peerDependenciesMeta: + '@emotion/is-prop-valid': + optional: true + react: + optional: true + react-dom: + optional: true + fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} @@ -1756,6 +1786,9 @@ packages: peerDependencies: react: '>=17.0' + tailwind-merge@2.5.4: + resolution: {integrity: sha512-0q8cfZHMu9nuYP/b5Shb7Y7Sh1B7Nnl5GqNr1U+n2p6+mybvRtayrQ+0042Z5byvTA8ihjlP8Odo8/VnHbZu4Q==} + tailwindcss@3.4.3: resolution: {integrity: sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==} engines: {node: '>=14.0.0'} @@ -1951,6 +1984,24 @@ packages: react: optional: true + zustand@5.0.1: + resolution: {integrity: sha512-pRET7Lao2z+n5R/HduXMio35TncTlSW68WsYBq2Lg1ASspsNGjpwLAsij3RpouyV6+kHMwwwzP0bZPD70/Jx/w==} + engines: {node: '>=12.20.0'} + peerDependencies: + '@types/react': '>=18.0.0' + immer: '>=9.0.6' + react: '>=18.0.0' + use-sync-external-store: '>=1.2.0' + peerDependenciesMeta: + '@types/react': + optional: true + immer: + optional: true + react: + optional: true + use-sync-external-store: + optional: true + snapshots: '@alloc/quick-lru@5.2.0': {} @@ -2483,6 +2534,8 @@ snapshots: client-only@0.0.1: {} + clsx@2.1.1: {} + color-convert@2.0.1: dependencies: color-name: 1.1.4 @@ -2687,8 +2740,8 @@ snapshots: '@typescript-eslint/parser': 7.2.0(eslint@8.57.0)(typescript@5.4.5) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) eslint-plugin-jsx-a11y: 6.8.0(eslint@8.57.0) eslint-plugin-react: 7.34.1(eslint@8.57.0) eslint-plugin-react-hooks: 4.6.2(eslint@8.57.0) @@ -2710,13 +2763,13 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0): + eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0): dependencies: debug: 4.3.4 enhanced-resolve: 5.16.1 eslint: 8.57.0 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) fast-glob: 3.3.2 get-tsconfig: 4.7.5 is-core-module: 2.13.1 @@ -2727,18 +2780,18 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): + eslint-module-utils@2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 7.2.0(eslint@8.57.0)(typescript@5.4.5) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0) transitivePeerDependencies: - supports-color - eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): + eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): dependencies: array-includes: 3.1.8 array.prototype.findlastindex: 1.2.5 @@ -2748,7 +2801,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.2.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) hasown: 2.0.2 is-core-module: 2.13.1 is-glob: 4.0.3 @@ -2931,6 +2984,13 @@ snapshots: cross-spawn: 7.0.3 signal-exit: 4.1.0 + framer-motion@11.11.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + tslib: 2.6.2 + optionalDependencies: + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + fs.realpath@1.0.0: {} fsevents@2.3.3: @@ -3759,6 +3819,8 @@ snapshots: dependencies: react: 18.3.1 + tailwind-merge@2.5.4: {} + tailwindcss@3.4.3: dependencies: '@alloc/quick-lru': 5.2.0 @@ -3994,3 +4056,9 @@ snapshots: optionalDependencies: '@types/react': 18.3.3 react: 18.3.1 + + zustand@5.0.1(@types/react@18.3.3)(react@18.3.1)(use-sync-external-store@1.2.0(react@18.3.1)): + optionalDependencies: + '@types/react': 18.3.3 + react: 18.3.1 + use-sync-external-store: 1.2.0(react@18.3.1) diff --git a/public/images/vex.jpg b/public/images/vex.jpg new file mode 100644 index 0000000..8542de6 Binary files /dev/null and b/public/images/vex.jpg differ diff --git a/public/models/Astronaut1.glb b/public/models/Astronaut1.glb new file mode 100644 index 0000000..c72fd90 Binary files /dev/null and b/public/models/Astronaut1.glb differ diff --git a/public/models/LogoBreaks.glb b/public/models/LogoBreaks.glb new file mode 100644 index 0000000..73ea08b Binary files /dev/null and b/public/models/LogoBreaks.glb differ diff --git a/src/app/page.tsx b/src/app/page.tsx index fbfef54..e8d952e 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -14,7 +14,7 @@ import Loader from '@/components/Loader/loader'; import CustomCursor from '@/components/customCursor/customCursor'; import { useLoading } from '../context/loadingContext'; -import { useEffect } from 'react'; +import { useEffect, useState } from 'react'; import { useProgress } from '@react-three/drei'; import Lenis from 'lenis'; @@ -26,6 +26,7 @@ gsap.registerPlugin(ScrollTrigger); export default function Home() { const { progress } = useProgress(); const { isLoaded, setIsLoaded } = useLoading(); + const [isCornersLoaded, setIsCornersLoaded] = useState(false); useEffect(() => { if (progress === 100) { @@ -36,23 +37,21 @@ export default function Home() { useEffect(() => { const lenis = new Lenis({ lerp: 0.1, - wheelMultiplier: 0.6, - touchMultiplier: 0.6, + wheelMultiplier: 0.4, + touchMultiplier: 0.4, }); + lenis.scrollTo(0, { immediate: true }); function raf(time: number) { lenis.raf(time); requestAnimationFrame(raf); } - requestAnimationFrame(raf); lenis.on('scroll', ScrollTrigger.update); - gsap.ticker.add((time) => { lenis.raf(time * 1000); }); - gsap.ticker.lagSmoothing(0); return () => { @@ -69,8 +68,8 @@ export default function Home() { {isLoaded && }
- {isLoaded && } - + {isLoaded && } + @@ -78,7 +77,7 @@ export default function Home() { - +
); diff --git a/src/components/3dModel/aeriusLogo.tsx b/src/components/3dModel/aeriusLogo.tsx index aab23ba..7a6725e 100644 --- a/src/components/3dModel/aeriusLogo.tsx +++ b/src/components/3dModel/aeriusLogo.tsx @@ -1,131 +1,138 @@ import { useAnimations, useGLTF } from '@react-three/drei'; import { useFrame } from '@react-three/fiber'; -import { useEffect, useRef } from 'react'; +import { useRef, useMemo, useState } from 'react'; import gsap from 'gsap'; import ScrollTrigger from 'gsap/ScrollTrigger'; -import { Color, Euler, Vector2 } from 'three'; +import { Color, DoubleSide } from 'three'; import { useGSAP } from '@gsap/react'; gsap.registerPlugin(ScrollTrigger); gsap.registerPlugin(useGSAP); -useGLTF.preload('/models/logoBreak.glb'); +useGLTF.preload('/models/LogoBreaks.glb'); export default function AeriusLogoModel() { const group = useRef(); - const model: any = useGLTF('/models/logoBreak.glb'); - + const model = useGLTF('/models/LogoBreaks.glb'); const { animations, nodes, materials } = model; const { mixer } = useAnimations(animations, group); + const [load, setLoad] = useState(false); + + const createBaseMaterial = () => { + const material: any = materials['Material'].clone(); + material.metalness = 0.9; + material.roughness = 0.2; + material.opacity = 0; + material.transparent = true; + material.depthWrite = false; + material.side = DoubleSide; + material.alphaTest = 0.01; + material.color = new Color(0.6, 0.06, 1); + material.emissiveIntensity = 1.2; + material.envMapIntensity = 1.5; + return material; + }; + + const meshMaterials = useMemo(() => { + return Object.keys(nodes).map(() => createBaseMaterial()); + }, [nodes]); - useEffect(() => { - materials['Frosted Glass 01'].aoMapIntensity = 1; - materials['Frosted Glass 01'].blendAlpha = 0; - materials['Frosted Glass 01'].blendColor = new Color(0, 0, 0); - materials['Frosted Glass 01'].blendDst = 205; - materials['Frosted Glass 01'].blendEquation = 100; - materials['Frosted Glass 01'].blendSrc = 204; - materials['Frosted Glass 01'].blending = 1; - materials['Frosted Glass 01'].bumpScale = 1; - materials['Frosted Glass 01'].color = new Color( - 0.5972017883558645, - 0.06301001764564068, - 1 + useGSAP(() => { + const layerOneAnimation: any = animations.find( + (clip) => clip.name === 'Layer_001Action.001' ); - materials['Frosted Glass 01'].colorWrite = true; - materials['Frosted Glass 01'].depthFunc = 3; - materials['Frosted Glass 01'].depthTest = true; - materials['Frosted Glass 01'].depthWrite = true; - materials['Frosted Glass 01'].displacementScale = 1; - materials['Frosted Glass 01'].dust = 1; - materials['Frosted Glass 01'].emissive = new Color(0, 0, 0); - materials['Frosted Glass 01'].emissiveIntensity = 1; - materials['Frosted Glass 01'].envMapIntensity = 1; - materials['Frosted Glass 01'].envMapRotation = new Euler(0, 0, 0, 'XYZ'); - materials['Frosted Glass 01'].fog = true; - materials['Frosted Glass 01'].ior = 1.85; - materials['Frosted Glass 01'].isMaterial = true; - materials['Frosted Glass 01'].isMeshStandardMaterial = true; - materials['Frosted Glass 01'].lightMapIntensity = 1; - materials['Frosted Glass 01'].metalness = 0.9; - materials['Frosted Glass 01'].name = 'Frosted Glass 01'; - materials['Frosted Glass 01'].normalScale = new Vector2(1, -1); - materials['Frosted Glass 01'].opacity = 0.9; - materials['Frosted Glass 01'].reflection = new Color( - 1, - 0.17144110072255403, - 0.9301108583738498 + const layerOneAction: any = mixer.clipAction(layerOneAnimation); + layerOneAction.clampWhenFinished = true; + layerOneAction.loop = false; + layerOneAction.play(); + + const explosionAnimations = animations.filter( + (clip) => !clip.name.includes('Layer_001') ); - materials['Frosted Glass 01'].refractionFactor = 0.9; - materials['Frosted Glass 01'].roughness = 0.2; - materials['Frosted Glass 01'].shininess = 0.5; - materials['Frosted Glass 01'].side = 2; - materials['Frosted Glass 01'].stencilFail = 7680; - materials['Frosted Glass 01'].stencilFunc = 519; - materials['Frosted Glass 01'].stencilFuncMask = 255; - materials['Frosted Glass 01'].stencilWriteMask = 255; - materials['Frosted Glass 01'].stencilZFail = 7680; - materials['Frosted Glass 01'].stencilZPass = 7680; - materials['Frosted Glass 01'].toneMapped = true; - materials['Frosted Glass 01'].transparent = true; - }, []); - useGSAP(() => { - // Play the actions once to initialize them - animations.forEach((clip: any) => { - const action = mixer.clipAction(clip); + const explosionActions = explosionAnimations.map((clip) => { + const action: any = mixer.clipAction(clip); + action.clampWhenFinished = true; + action.loop = false; action.paused = true; + return action; }); - // Register ScrollTrigger ScrollTrigger.create({ trigger: '#logoContainer', - start: 'top 40%', + start: 'top center', end: '+=150%', - scrub: 2, - onEnter: () => { - animations.forEach((clip: any) => { - const action = mixer.clipAction(clip); - action.play(); - }); - }, - onLeave: () => { - animations.forEach((clip: any) => { - const action = mixer.clipAction(clip); - action.paused = true; - }); - }, - onEnterBack: () => { - animations.forEach((clip: any) => { - const action = mixer.clipAction(clip); - action.play(); - }); - }, - onLeaveBack: () => { - animations.forEach((clip: any) => { - const action = mixer.clipAction(clip); - action.paused = true; - }); - }, + scrub: 1, onUpdate: (self) => { const progress = self.progress; - animations.forEach((clip: any) => { - const action = mixer.clipAction(clip); - action.paused = true; - action.time = clip.duration * progress; - }); - }, - }); + if (progress <= 0.5) { + const layerOneProgress = progress * 2; + Object.keys(nodes).forEach((nodeName, index) => { + if (nodeName === 'Logo_Main') { + meshMaterials[index].opacity = Math.min(layerOneProgress * 2, 1); + meshMaterials[index].depthWrite = + meshMaterials[index].opacity === 1; + } else if (nodeName.includes('Logo_Main001_cell')) { + meshMaterials[index].opacity = 0; + meshMaterials[index].depthWrite = false; + } + }); + layerOneAction.paused = true; + layerOneAction.time = + layerOneAction.getClip().duration * layerOneProgress; - ScrollTrigger.create({ - trigger: '#logoContainer', - start: 'top top', // Pin when the top of the logoContainer hits the top of the viewport - end: '+=50%', // End pinning when the bottom of the logoContainer hits the top of the viewport - pin: true, - scrub: 2, - pinSpacing: false, + explosionActions.forEach((action) => { + action.time = 0; + action.paused = true; + }); + } else if (progress <= 0.75) { + const explosionProgress = (progress - 0.5) * 4; + + Object.keys(nodes).forEach((nodeName, index) => { + if (nodeName === 'Logo_Main') { + meshMaterials[index].opacity = Math.max( + 0, + 1 - explosionProgress * 2 + ); + meshMaterials[index].depthWrite = + meshMaterials[index].opacity === 1; + } else if (nodeName.includes('Logo_Main001_cell')) { + meshMaterials[index].opacity = Math.min(explosionProgress * 2, 1); + meshMaterials[index].depthWrite = + meshMaterials[index].opacity === 1; + } + }); + + layerOneAction.time = layerOneAction.getClip().duration; + layerOneAction.paused = true; + + explosionActions.forEach((action) => { + action.time = action.getClip().duration * explosionProgress; + action.play(); + action.paused = true; + }); + } else { + const fadeOutProgress = (progress - 0.75) * 4; + + Object.keys(nodes).forEach((nodeName, index) => { + if (nodeName.includes('Logo_Main001_cell')) { + meshMaterials[index].opacity = Math.max(0, 1 - fadeOutProgress); + meshMaterials[index].depthWrite = + meshMaterials[index].opacity === 1; + } else { + meshMaterials[index].opacity = 0; + meshMaterials[index].depthWrite = false; + } + }); + + explosionActions.forEach((action) => { + action.time = action.getClip().duration; + action.paused = true; + }); + } + }, }); - }, [mixer]); + }, [mixer, meshMaterials, animations, nodes]); useFrame((state, delta) => { mixer?.update(delta); @@ -134,1463 +141,27 @@ export default function AeriusLogoModel() { return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + {Object.keys(nodes).map((nodeName, index) => { + if ( + nodeName === 'Logo_Main' || + nodeName.includes('Logo_Main001_cell') + ) { + return ( + + ); + } + return null; + })} ); diff --git a/src/components/3dModel/astronaut.tsx b/src/components/3dModel/astronaut.tsx index 5a6684d..bcb75d2 100644 --- a/src/components/3dModel/astronaut.tsx +++ b/src/components/3dModel/astronaut.tsx @@ -1,2101 +1,180 @@ import { useAnimations, useGLTF } from '@react-three/drei'; import { useFrame } from '@react-three/fiber'; -import { useEffect, useRef } from 'react'; +import { useEffect, useRef, useMemo } from 'react'; import gsap from 'gsap'; import ScrollTrigger from 'gsap/ScrollTrigger'; -import { Color, Euler, Vector2 } from 'three'; import { useGSAP } from '@gsap/react'; +import { Color, MeshStandardMaterial } from 'three'; gsap.registerPlugin(ScrollTrigger); gsap.registerPlugin(useGSAP); -useGLTF.preload('/models/astronaut.glb'); +useGLTF.preload('/models/Astronaut1.glb'); export default function AstronautModel() { const group = useRef(null); const { nodes, materials, animations }: any = useGLTF( - '/models/astronaut.glb' + '/models/Astronaut1.glb' ); - const { mixer } = useAnimations(animations, group); + const { mixer, actions } = useAnimations(animations, group); + const logoMaterialsRef = useRef([]); - useEffect(() => { - materials['Frosted Glass 01'].aoMapIntensity = 1; - materials['Frosted Glass 01'].blendAlpha = 0; - materials['Frosted Glass 01'].blendColor = new Color(0, 0, 0); - materials['Frosted Glass 01'].blendDst = 205; - materials['Frosted Glass 01'].blendEquation = 100; - materials['Frosted Glass 01'].blendSrc = 204; - materials['Frosted Glass 01'].blending = 1; - materials['Frosted Glass 01'].bumpScale = 1; - materials['Frosted Glass 01'].color = new Color( - 0.5972017883558645, - 0.06301001764564068, - 1 - ); - materials['Frosted Glass 01'].colorWrite = true; - materials['Frosted Glass 01'].depthFunc = 3; - materials['Frosted Glass 01'].depthTest = true; - materials['Frosted Glass 01'].depthWrite = true; - materials['Frosted Glass 01'].displacementScale = 1; - materials['Frosted Glass 01'].dust = 1; - materials['Frosted Glass 01'].emissive = new Color(0, 0, 0); - materials['Frosted Glass 01'].emissiveIntensity = 1; - materials['Frosted Glass 01'].envMapIntensity = 1; - materials['Frosted Glass 01'].envMapRotation = new Euler(0, 0, 0, 'XYZ'); - materials['Frosted Glass 01'].fog = true; - materials['Frosted Glass 01'].ior = 1.85; - materials['Frosted Glass 01'].isMaterial = true; - materials['Frosted Glass 01'].isMeshStandardMaterial = true; - materials['Frosted Glass 01'].lightMapIntensity = 1; - materials['Frosted Glass 01'].metalness = 0.9; - materials['Frosted Glass 01'].name = 'Frosted Glass 01'; - materials['Frosted Glass 01'].normalScale = new Vector2(1, -1); - materials['Frosted Glass 01'].opacity = 0.9; - materials['Frosted Glass 01'].reflection = new Color( - 1, - 0.17144110072255403, - 0.9301108583738498 + const clonedMaterials = useMemo(() => { + if (!materials) return null; + return Object.entries(materials).reduce( + (acc: any, [key, material]: any) => { + const clonedMaterial = material.clone(); + clonedMaterial.transparent = true; + clonedMaterial.opacity = 0; + acc[key] = clonedMaterial; + return acc; + }, + {} ); - materials['Frosted Glass 01'].refractionFactor = 0.9; - materials['Frosted Glass 01'].roughness = 0.1; - materials['Frosted Glass 01'].shininess = 0.5; - materials['Frosted Glass 01'].side = 2; - materials['Frosted Glass 01'].stencilFail = 7680; - materials['Frosted Glass 01'].stencilFunc = 519; - materials['Frosted Glass 01'].stencilFuncMask = 255; - materials['Frosted Glass 01'].stencilWriteMask = 255; - materials['Frosted Glass 01'].stencilZFail = 7680; - materials['Frosted Glass 01'].stencilZPass = 7680; - materials['Frosted Glass 01'].toneMapped = true; - materials['Frosted Glass 01'].transparent = true; + }, [materials]); - materials['Glass Gradient'].alphaToCoverage = false; - materials['Glass Gradient'].anisotropyMap = null; - materials['Glass Gradient'].anisotropyRotation = 0; - materials['Glass Gradient'].aoMap = null; - materials['Glass Gradient'].aoMapIntensity = 1; - materials['Glass Gradient'].attenuationColor = new Color(1, 1, 1); - materials['Glass Gradient'].attenuationDistance = Infinity; - materials['Glass Gradient'].blendAlpha = 0; - materials['Glass Gradient'].blendColor = new Color(0, 0, 0); - materials['Glass Gradient'].blendDst = 205; - materials['Glass Gradient'].blendDstAlpha = null; - materials['Glass Gradient'].blendEquation = 100; - materials['Glass Gradient'].blendEquationAlpha = null; - materials['Glass Gradient'].blendSrc = 204; - materials['Glass Gradient'].blendSrcAlpha = null; - materials['Glass Gradient'].blending = 1; - materials['Glass Gradient'].bumpMap = null; - materials['Glass Gradient'].bumpScale = 1; - materials['Glass Gradient'].clearcoatMap = null; - materials['Glass Gradient'].clearcoatNormalMap = null; - materials['Glass Gradient'].clearcoatNormalScale = new Vector2(1, -1); - materials['Glass Gradient'].clearcoatRoughness = 0; - materials['Glass Gradient'].clearcoatRoughnessMap = null; - materials['Glass Gradient'].clipIntersection = false; - materials['Glass Gradient'].clipShadows = false; - materials['Glass Gradient'].clippingPlanes = null; - materials['Glass Gradient'].color = new Color(1, 1, 1); - materials['Glass Gradient'].colorWrite = true; - materials['Glass Gradient'].defines = { STANDARD: '', PHYSICAL: '' }; - materials['Glass Gradient'].depthFunc = 3; - materials['Glass Gradient'].depthTest = true; - materials['Glass Gradient'].depthWrite = true; - materials['Glass Gradient'].displacementBias = 0; - materials['Glass Gradient'].displacementMap = null; - materials['Glass Gradient'].displacementScale = 1; - materials['Glass Gradient'].dithering = false; - materials['Glass Gradient'].emissive = new Color(0, 0, 0); - materials['Glass Gradient'].emissiveIntensity = 1; - materials['Glass Gradient'].emissiveMap = null; - materials['Glass Gradient'].envMap = null; - materials['Glass Gradient'].envMapIntensity = 1; - materials['Glass Gradient'].envMapRotation = new Euler(0, 0, 0, 'XYZ'); - materials['Glass Gradient'].flatShading = false; - materials['Glass Gradient'].fog = true; - materials['Glass Gradient'].forceSinglePass = false; - materials['Glass Gradient'].ior = 1.4500000476837158; - materials['Glass Gradient'].iridescenceIOR = 1.3; - materials['Glass Gradient'].iridescenceMap = null; - materials['Glass Gradient'].iridescenceThicknessMap = null; - materials['Glass Gradient'].iridescenceThicknessRange = [100, 400]; - materials['Glass Gradient'].isMaterial = true; - materials['Glass Gradient'].isMeshPhysicalMaterial = true; - materials['Glass Gradient'].isMeshStandardMaterial = true; - materials['Glass Gradient'].lightMap = null; - materials['Glass Gradient'].lightMapIntensity = 1; - materials['Glass Gradient'].map = null; - materials['Glass Gradient'].metalness = 0.7; - materials['Glass Gradient'].metalnessMap = null; - materials['Glass Gradient'].name = 'Glass Gradient'; - materials['Glass Gradient'].normalMap = null; - materials['Glass Gradient'].normalMapType = 0; - materials['Glass Gradient'].normalScale = new Vector2(1, -1); - materials['Glass Gradient'].opacity = 1; - materials['Glass Gradient'].polygonOffset = false; - materials['Glass Gradient'].polygonOffsetFactor = 0; - materials['Glass Gradient'].polygonOffsetUnits = 0; - materials['Glass Gradient'].precision = null; - materials['Glass Gradient'].premultipliedAlpha = false; - materials['Glass Gradient'].roughness = 0.2; - materials['Glass Gradient'].roughnessMap = null; - materials['Glass Gradient'].shadowSide = null; - materials['Glass Gradient'].sheenColor = new Color(0, 0, 0); - materials['Glass Gradient'].sheenColorMap = null; - materials['Glass Gradient'].sheenRoughness = 1; - materials['Glass Gradient'].sheenRoughnessMap = null; - materials['Glass Gradient'].side = 2; - materials['Glass Gradient'].specularColor = new Color(1, 1, 1); - materials['Glass Gradient'].specularColorMap = null; - materials['Glass Gradient'].specularIntensity = 1; - materials['Glass Gradient'].specularIntensityMap = null; - materials['Glass Gradient'].stencilFail = 7680; - materials['Glass Gradient'].stencilFunc = 519; - materials['Glass Gradient'].stencilFuncMask = 255; - materials['Glass Gradient'].stencilRef = 0; - materials['Glass Gradient'].stencilWrite = false; - materials['Glass Gradient'].stencilWriteMask = 255; - materials['Glass Gradient'].stencilZFail = 7680; - materials['Glass Gradient'].stencilZPass = 7680; - materials['Glass Gradient'].thickness = 0; - materials['Glass Gradient'].thicknessMap = null; - materials['Glass Gradient'].toneMapped = true; - materials['Glass Gradient'].transmissionMap = null; - materials['Glass Gradient'].transparent = false; - materials['Glass Gradient'].type = 'MeshPhysicalMaterial'; - materials['Glass Gradient'].userData = {}; - materials['Glass Gradient'].uuid = '502aee9e-bbfe-42c7-b759-2a859eccf50d'; - materials['Glass Gradient'].version = 6243; - materials['Glass Gradient'].vertexColors = false; - materials['Glass Gradient'].visible = true; - materials['Glass Gradient'].wireframe = false; - materials['Glass Gradient'].wireframeLinecap = 'round'; - materials['Glass Gradient'].wireframeLinejoin = 'round'; - materials['Glass Gradient'].wireframeLinewidth = 1; - }, []); + useEffect(() => { + if (!actions || !mixer) return; + Object.values(actions).forEach((action: any) => { + if (action) { + action.reset(); + action.play(); + action.paused = true; + } + }); + }, [actions, mixer]); useGSAP(() => { - // Play the actions once to initialize them - animations.forEach((clip: any) => { - const action = mixer.clipAction(clip); - action.paused = true; + if (!mixer || !actions || !clonedMaterials) return; + const tl = gsap.timeline({ + scrollTrigger: { + trigger: '#astronautContainer', + start: 'top 0', + end: '+=200%', + scrub: 1, + markers: false, + pin: true, + onUpdate: (self) => { + const progress = self.progress; + Object.values(actions).forEach((action: any) => { + if (action) { + action.time = action.getClip().duration * progress; + mixer.update(0); + } + }); + }, + onLeave: () => { + Object.values(actions).forEach((action: any) => { + if (action) action.paused = true; + }); + }, + onEnterBack: () => { + Object.values(actions).forEach((action: any) => { + if (action) action.paused = true; + }); + }, + }, }); - // Register ScrollTrigger ScrollTrigger.create({ trigger: '#astronautContainer', - start: 'top 40%', - end: '+=280%', + start: 'top 10%', + end: 'top -220%', scrub: 2, - onEnter: () => { - animations.forEach((clip: any) => { - const action = mixer.clipAction(clip); - action.play(); - }); - }, - onLeave: () => { - animations.forEach((clip: any) => { - const action = mixer.clipAction(clip); - action.paused = true; - }); - }, - onEnterBack: () => { - animations.forEach((clip: any) => { - const action = mixer.clipAction(clip); - action.play(); - }); - }, - onLeaveBack: () => { - animations.forEach((clip: any) => { - const action = mixer.clipAction(clip); - action.paused = true; - }); - }, onUpdate: (self) => { - const progress = self.progress; - animations.forEach((clip: any) => { - const action = mixer.clipAction(clip); - action.paused = true; - action.time = clip.duration * progress; + let opacity = 0; + if (self.progress < 0.1) { + opacity = self.progress * 10; + } else if (self.progress >= 0.8) { + opacity = 1 - (self.progress - 0.8) / 0.2; + } else { + opacity = 1; + } + opacity = Math.max(0, Math.min(1, opacity)); + Object.values(clonedMaterials).forEach((material: any) => { + material.opacity = opacity; + }); + logoMaterialsRef.current.forEach((material) => { + if (material) { + material.opacity = opacity * 0.7; + } }); }, }); - ScrollTrigger.create({ - trigger: '#astronautContainer', - start: 'top top', // Pin when the top of the logoContainer hits the top of the viewport - end: '+=180%', // End pinning when the bottom of the logoContainer hits the top of the viewport - pin: true, - scrub: 2, - }); - - return () => { - ScrollTrigger.getAll().forEach((trigger) => trigger.kill()); - }; - }, [mixer]); + return () => tl.kill(); + }, [mixer, actions, clonedMaterials]); useFrame((_, delta) => { - mixer?.update(delta); + if (mixer && (ScrollTrigger as any).isScrolling) { + mixer.update(delta); + } }); + if (!clonedMaterials || !nodes) return null; + return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + {nodes.Armature001 && ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + name='Armature001' + position={[-4.452, -11.697, -12.968]} + rotation={[1.461, 0, 0]} + scale={0.1} + renderOrder={2} + > + {nodes.Ch44001 && clonedMaterials['Material'] && ( + + )} + {nodes.Ch44002 && clonedMaterials['Glass Gradient'] && ( + + )} + {nodes.mixamorigHips && } + + )} + + {Object.keys(nodes) + .filter((key) => key.includes('Logo_Main001_cell')) + .map((nodeName, index) => { + const material = new MeshStandardMaterial({ + color: '#67009a', + emissive: '#67009a', + emissiveIntensity: 1.5, + transparent: true, + opacity: 0, + }); + logoMaterialsRef.current[index] = material; + return ( + + ); + })} diff --git a/src/components/3dModel/satellite.tsx b/src/components/3dModel/satellite.tsx index 756a5e2..5be2935 100644 --- a/src/components/3dModel/satellite.tsx +++ b/src/components/3dModel/satellite.tsx @@ -1,6 +1,6 @@ import { useAnimations, useGLTF } from '@react-three/drei'; import { useFrame } from '@react-three/fiber'; -import { useEffect, useRef } from 'react'; +import { useEffect, useRef, useMemo } from 'react'; import gsap from 'gsap'; import ScrollTrigger from 'gsap/ScrollTrigger'; import { Color, Euler, Vector2 } from 'three'; @@ -9,90 +9,101 @@ import { useGSAP } from '@gsap/react'; gsap.registerPlugin(ScrollTrigger); gsap.registerPlugin(useGSAP); -useGLTF.preload('/models/satellite.glb'); +useGLTF.preload('/models/Satellite.glb'); export default function SatelliteModel() { const group = useRef(null); const { nodes, materials, animations }: any = useGLTF( - '/models/satellite.glb' + '/models/Satellite.glb' ); const { mixer } = useAnimations(animations, group); + const clonedMaterials = useMemo(() => { + return { + 'Frosted Glass 01': materials['Frosted Glass 01'].clone(), + 'tie fighter window ': materials['tie fighter window '].clone(), + 'tie fighter base': materials['tie fighter base'].clone(), + 'TIE FIGHTER WING': materials['TIE FIGHTER WING'].clone(), + }; + }, [materials]); + useEffect(() => { - materials['Frosted Glass 01'].aoMapIntensity = 1; - materials['Frosted Glass 01'].blendAlpha = 0; - materials['Frosted Glass 01'].blendColor = new Color(0, 0, 0); - materials['Frosted Glass 01'].blendDst = 205; - materials['Frosted Glass 01'].blendEquation = 100; - materials['Frosted Glass 01'].blendSrc = 204; - materials['Frosted Glass 01'].blending = 1; - materials['Frosted Glass 01'].bumpScale = 1; - materials['Frosted Glass 01'].color = new Color( + // Frosted Glass setup + clonedMaterials['Frosted Glass 01'].aoMapIntensity = 1; + clonedMaterials['Frosted Glass 01'].blendAlpha = 0; + clonedMaterials['Frosted Glass 01'].blendColor = new Color(0, 0, 0); + clonedMaterials['Frosted Glass 01'].blendDst = 205; + clonedMaterials['Frosted Glass 01'].blendEquation = 100; + clonedMaterials['Frosted Glass 01'].blendSrc = 204; + clonedMaterials['Frosted Glass 01'].blending = 1; + clonedMaterials['Frosted Glass 01'].bumpScale = 1; + clonedMaterials['Frosted Glass 01'].color = new Color( 0.5972017883558645, 0.06301001764564068, 1 ); - materials['Frosted Glass 01'].colorWrite = true; - materials['Frosted Glass 01'].depthFunc = 3; - materials['Frosted Glass 01'].depthTest = true; - materials['Frosted Glass 01'].depthWrite = true; - materials['Frosted Glass 01'].displacementScale = 1; - materials['Frosted Glass 01'].dust = 1; - materials['Frosted Glass 01'].emissive = new Color(0, 0, 0); - materials['Frosted Glass 01'].emissiveIntensity = 1; - materials['Frosted Glass 01'].envMapIntensity = 1; - materials['Frosted Glass 01'].envMapRotation = new Euler(0, 0, 0, 'XYZ'); - materials['Frosted Glass 01'].fog = true; - materials['Frosted Glass 01'].ior = 1.85; - materials['Frosted Glass 01'].isMaterial = true; - materials['Frosted Glass 01'].isMeshStandardMaterial = true; - materials['Frosted Glass 01'].lightMapIntensity = 1; - materials['Frosted Glass 01'].metalness = 0.9; - materials['Frosted Glass 01'].name = 'Frosted Glass 01'; - materials['Frosted Glass 01'].normalScale = new Vector2(1, -1); - materials['Frosted Glass 01'].opacity = 0.9; - materials['Frosted Glass 01'].reflection = new Color( - 1, - 0.17144110072255403, - 0.9301108583738498 + clonedMaterials['Frosted Glass 01'].colorWrite = true; + clonedMaterials['Frosted Glass 01'].depthFunc = 3; + clonedMaterials['Frosted Glass 01'].depthTest = true; + clonedMaterials['Frosted Glass 01'].depthWrite = true; + clonedMaterials['Frosted Glass 01'].displacementScale = 1; + clonedMaterials['Frosted Glass 01'].dust = 1; + clonedMaterials['Frosted Glass 01'].emissive = new Color(0, 0, 0); + clonedMaterials['Frosted Glass 01'].emissiveIntensity = 1; + clonedMaterials['Frosted Glass 01'].envMapIntensity = 1; + clonedMaterials['Frosted Glass 01'].envMapRotation = new Euler( + 0, + 0, + 0, + 'XYZ' ); - materials['Frosted Glass 01'].refractionFactor = 0.54; - materials['Frosted Glass 01'].roughness = 0.2; - materials['Frosted Glass 01'].shininess = 0.5; - materials['Frosted Glass 01'].side = 2; - materials['Frosted Glass 01'].stencilFail = 7680; - materials['Frosted Glass 01'].stencilFunc = 519; - materials['Frosted Glass 01'].stencilFuncMask = 255; - materials['Frosted Glass 01'].stencilWriteMask = 255; - materials['Frosted Glass 01'].stencilZFail = 7680; - materials['Frosted Glass 01'].stencilZPass = 7680; - materials['Frosted Glass 01'].toneMapped = true; - materials['Frosted Glass 01'].transparent = true; + clonedMaterials['Frosted Glass 01'].fog = true; + clonedMaterials['Frosted Glass 01'].ior = 1.85; + clonedMaterials['Frosted Glass 01'].metalness = 0.9; + clonedMaterials['Frosted Glass 01'].normalScale = new Vector2(1, -1); + clonedMaterials['Frosted Glass 01'].opacity = 0.9; + clonedMaterials['Frosted Glass 01'].roughness = 5; + clonedMaterials['Frosted Glass 01'].transparent = true; + + // Other materials setup + clonedMaterials['tie fighter window '].roughness = 0.3; + clonedMaterials['tie fighter window '].metalness = 1; + clonedMaterials['tie fighter window '].transparent = true; - materials['tie fighter window '].roughness = 0.3; - materials['tie fighter window '].metalness = 1; + clonedMaterials['tie fighter base'].roughness = 0.2; + clonedMaterials['tie fighter base'].transparent = true; - materials['tie fighter base'].roughness = 0.2; - }, []); + clonedMaterials['TIE FIGHTER WING'].fog = true; + clonedMaterials['TIE FIGHTER WING'].transparent = true; + + // Set initial opacity for all materials + Object.values(clonedMaterials).forEach((material) => { + material.opacity = material.opacity || 1; + }); + }, [clonedMaterials]); useGSAP(() => { - // Play the actions once to initialize them + // Animation setup animations.forEach((clip: any) => { const action = mixer.clipAction(clip); action.paused = true; }); - // Register ScrollTrigger + // Main animation trigger ScrollTrigger.create({ trigger: '#satelliteContainer', start: 'top 40%', - end: '+=380%', + end: '+=320%', scrub: 2, onEnter: () => { animations.forEach((clip: any) => { const action = mixer.clipAction(clip); action.play(); }); + let opacity = 0.5; + Object.values(clonedMaterials).forEach((material) => { + material.opacity = opacity; + }); }, onLeave: () => { animations.forEach((clip: any) => { @@ -122,15 +133,36 @@ export default function SatelliteModel() { }, }); + // Fade effect trigger + ScrollTrigger.create({ + trigger: '#satelliteContainer', + start: 'top -20%', + end: 'top -270%', + scrub: 2, + onUpdate: (self) => { + // Calculate opacity based on scroll progress + let opacity = Math.max(0, 0.5 + self.progress); + if (self.progress >= 0.8) opacity = 1 - (self.progress - 0.8) / 0.17; + Object.values(clonedMaterials).forEach((material) => { + material.opacity = opacity; + }); + }, + }); + + // Pin trigger ScrollTrigger.create({ trigger: '#satelliteContainer', - start: 'top top', // Pin when the top of the logoContainer hits the top of the viewport - end: '+=280%', // End pinning when the bottom of the logoContainer hits the top of the viewport + start: 'top top', + end: '+=280%', pin: true, scrub: 2, pinSpacing: false, }); - }, [mixer]); + + return () => { + ScrollTrigger.getAll().forEach((trigger) => trigger.kill()); + }; + }, [mixer, clonedMaterials]); useFrame((_, delta) => { mixer?.update(delta); @@ -144,7 +176,7 @@ export default function SatelliteModel() { castShadow receiveShadow geometry={nodes.Tie_fighter.geometry} - material={materials['tie fighter base']} + material={clonedMaterials['tie fighter base']} position={[-4.748, -2.222, -20.396]} rotation={[Math.PI, -1.229, Math.PI]} scale={1.88} @@ -166,7 +198,7 @@ export default function SatelliteModel() { castShadow receiveShadow geometry={nodes.glass_.geometry} - material={materials['tie fighter window ']} + material={clonedMaterials['tie fighter window ']} position={[0.004, 0, 0]} rotation={[-Math.PI / 2, 0.023, -Math.PI / 2]} scale={1.002} @@ -176,7 +208,7 @@ export default function SatelliteModel() { castShadow receiveShadow geometry={nodes.glass_frame.geometry} - material={materials['tie fighter base']} + material={clonedMaterials['tie fighter base']} position={[0.004, 0, 0]} rotation={[-Math.PI / 2, 0.023, -Math.PI / 2]} scale={1.016} @@ -186,7 +218,7 @@ export default function SatelliteModel() { castShadow receiveShadow geometry={nodes.Retopo_other_glass_frame003.geometry} - material={materials['tie fighter base']} + material={clonedMaterials['tie fighter base']} position={[0.624, -0.014, 0]} rotation={[-Math.PI / 2, 0.023, -Math.PI / 2]} scale={0.784} @@ -196,7 +228,7 @@ export default function SatelliteModel() { castShadow receiveShadow geometry={nodes.wing_outer_frame.geometry} - material={materials['tie fighter base']} + material={clonedMaterials['tie fighter base']} position={[0.044, -2.2, 0]} rotation={[Math.PI / 2, -Math.PI / 6, 0]} scale={4.175} @@ -206,7 +238,7 @@ export default function SatelliteModel() { castShadow receiveShadow geometry={nodes.wing_panel_DO_NOT_JOIN_2.geometry} - material={materials['TIE FIGHTER WING']} + material={clonedMaterials['TIE FIGHTER WING']} position={[-0.012, -0.004, -2.295]} rotation={[Math.PI / 2, -Math.PI / 6, 0]} scale={4.189} @@ -216,7 +248,7 @@ export default function SatelliteModel() { castShadow receiveShadow geometry={nodes.wing_tech_pannel.geometry} - material={materials['tie fighter base']} + material={clonedMaterials['tie fighter base']} position={[-0.022, -0.013, 2.268]} rotation={[-1.571, -1.558, 0]} scale={0.24} @@ -226,7 +258,7 @@ export default function SatelliteModel() { castShadow receiveShadow geometry={nodes.wingbody_joiner.geometry} - material={materials['tie fighter base']} + material={clonedMaterials['tie fighter base']} position={[0.044, -2.2, 0]} rotation={[-Math.PI / 2, Math.PI / 2, 0]} scale={[0.061, 0.119, 0.119]} @@ -238,1822 +270,23 @@ export default function SatelliteModel() { rotation={[0.56, -0.671, 0.954]} scale={26.353} > - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + {Object.keys(nodes).map((nodeName) => { + if (nodeName.includes('Logo_Main001_cell')) { + return ( + + ); + } + return null; + })} diff --git a/src/components/BorderCorners/borderCorners.tsx b/src/components/BorderCorners/borderCorners.tsx index 3ae10ac..5631dcc 100644 --- a/src/components/BorderCorners/borderCorners.tsx +++ b/src/components/BorderCorners/borderCorners.tsx @@ -1,14 +1,135 @@ -export default function BorderCorners() { +import { gsap } from 'gsap'; +import { Power2 } from 'gsap/dist/gsap'; +import { SetStateAction, useEffect, useRef, Dispatch } from 'react'; + +export default function BorderCorners({ + setIsCornersLoaded, +}: { + setIsCornersLoaded: Dispatch>; +}) { + const topLeftRef = useRef(null); + const topRightRef = useRef(null); + const bottomLeftRef = useRef(null); + const bottomRightRef = useRef(null); + + useEffect(() => { + const corners = [ + topLeftRef.current, + topRightRef.current, + bottomLeftRef.current, + bottomRightRef.current, + ]; + gsap.set(corners[0], { + left: '47%', + top: '47%', + xPercent: -50, + yPercent: -50, + scale: 0, + opacity: 0, + }); + gsap.set(corners[1], { + left: '53%', + top: '47%', + xPercent: -50, + yPercent: -50, + scale: 0, + opacity: 0, + }); + gsap.set(corners[2], { + left: '47%', + top: '53%', + xPercent: -50, + yPercent: -50, + scale: 0, + opacity: 0, + }); + gsap.set(corners[3], { + left: '53%', + top: '53%', + xPercent: -50, + yPercent: -50, + scale: 0, + opacity: 0, + }); + + gsap + .timeline({ + onComplete: () => setIsCornersLoaded(true), + }) + .to(corners, { + opacity: 1, + scale: 1, + duration: 1, + ease: Power2.easeOut, + }) + .to( + topLeftRef.current, + { + left: '2%', + top: '2%', + xPercent: 0, + yPercent: 0, + duration: 2, + ease: Power2.easeInOut, + }, + '-=0.5' + ) + .to( + topRightRef.current, + { + left: '98%', + top: '2%', + xPercent: -100, + yPercent: 0, + duration: 2, + ease: Power2.easeInOut, + }, + '-=2' + ) + .to( + bottomLeftRef.current, + { + left: '2%', + top: '98%', + xPercent: 0, + yPercent: -100, + duration: 2, + ease: Power2.easeInOut, + }, + '-=2' + ) + .to( + bottomRightRef.current, + { + left: '98%', + top: '98%', + xPercent: -100, + yPercent: -100, + duration: 2, + ease: Power2.easeInOut, + }, + '-=2' + ); + }, []); + return ( -
-
-
-
-
-
-
-
-
+
+
+
+
+
); } diff --git a/src/components/customCursor/customCursor.tsx b/src/components/customCursor/customCursor.tsx index bb8c069..93da07b 100644 --- a/src/components/customCursor/customCursor.tsx +++ b/src/components/customCursor/customCursor.tsx @@ -1,61 +1,71 @@ -import { useEffect } from 'react'; +import React, { useEffect } from 'react'; import gsap from 'gsap'; const CustomCursor = () => { useEffect(() => { - // CursorFollow logic - const moveCursor = (e: MouseEvent) => { + // Cursor follow logic + const moveCursor = (e: any) => { gsap.to('.cursorFollower', { - x: e.clientX - 6, - y: e.clientY - 6, - duration: 1.5, - ease: 'power4.out', + x: e.clientX - 16, + y: e.clientY - 16, + duration: 0.8, + ease: 'power2.out', }); gsap.to('.cursor', { - x: e.clientX - 4, - y: e.clientY - 4, - duration: 0.5, - ease: 'power4.out', + x: e.clientX - 8, + y: e.clientY - 8, + duration: 0.3, + ease: 'power2.out', }); }; - document.addEventListener('mousemove', moveCursor); + // Hover logic for arrow + const arrowLink = document.querySelector('.group'); - // Hover logic const mouseEnter = () => { - gsap.set('.cursor', { display: 'none' }); + gsap.to('.cursor', { + opacity: 0, + duration: 0.3, + }); gsap.to('.cursorFollower', { scale: 2, + duration: 0.3, }); }; const mouseLeave = () => { - gsap.set('.cursor', { display: 'block' }); + gsap.to('.cursor', { + opacity: 1, + duration: 0.3, + }); gsap.to('.cursorFollower', { scale: 1, + duration: 0.3, }); }; - document.querySelectorAll('.hovering').forEach((el) => { - el.addEventListener('mouseenter', mouseEnter); - el.addEventListener('mouseleave', mouseLeave); - }); + document.addEventListener('mousemove', moveCursor); + + if (arrowLink) { + arrowLink.addEventListener('mouseenter', mouseEnter); + arrowLink.addEventListener('mouseleave', mouseLeave); + } return () => { document.removeEventListener('mousemove', moveCursor); - document.querySelectorAll('.hovering').forEach((el) => { - el.removeEventListener('mouseenter', mouseEnter); - el.removeEventListener('mouseleave', mouseLeave); - }); + if (arrowLink) { + arrowLink.removeEventListener('mouseenter', mouseEnter); + arrowLink.removeEventListener('mouseleave', mouseLeave); + } }; }, []); return ( <> -
-
+
+
-
+
); }; diff --git a/src/components/scene/aeriusLogoScene.tsx b/src/components/scene/aeriusLogoScene.tsx index 113c37b..0fc347b 100644 --- a/src/components/scene/aeriusLogoScene.tsx +++ b/src/components/scene/aeriusLogoScene.tsx @@ -1,9 +1,9 @@ import { Canvas } from '@react-three/fiber'; -import { Environment } from '@react-three/drei'; +import { Environment, Lightformer } from '@react-three/drei'; import AeriusLogoModel from '../3dModel/aeriusLogo'; import AdjustCamera from '@/helpers/handleCameraFOV'; -export default function AstronautScene() { +export default function AeriusScene() { return ( - - + + + + + + + diff --git a/src/components/scene/astronautScene.tsx b/src/components/scene/astronautScene.tsx index bf72a9f..01351b5 100644 --- a/src/components/scene/astronautScene.tsx +++ b/src/components/scene/astronautScene.tsx @@ -1,4 +1,4 @@ -import { Canvas } from '@react-three/fiber'; +import { Canvas, useLoader } from '@react-three/fiber'; import { Environment } from '@react-three/drei'; import AstronautModel from '../3dModel/astronaut'; import AdjustCamera from '@/helpers/handleCameraFOV'; @@ -17,22 +17,36 @@ export default function AstronautScene() { scale: -1, }} > - - + + + + - - diff --git a/src/components/scene/satelliteScene.tsx b/src/components/scene/satelliteScene.tsx index 867770e..4a68c5e 100644 --- a/src/components/scene/satelliteScene.tsx +++ b/src/components/scene/satelliteScene.tsx @@ -18,20 +18,20 @@ export default function SatelliteScene() { }} > + - diff --git a/src/components/section/aboutUsSection.tsx b/src/components/section/aboutUsSection.tsx index cfc9367..96bacc3 100644 --- a/src/components/section/aboutUsSection.tsx +++ b/src/components/section/aboutUsSection.tsx @@ -1,38 +1,91 @@ import Image from 'next/image'; import dynamic from 'next/dynamic'; import { Akzidenzgroteskbe, IBMPlexMono } from '@/fonts/fonts'; +import { useEffect, useRef } from 'react'; +import gsap from 'gsap'; +import { ScrollTrigger } from 'gsap/ScrollTrigger'; const Scene = dynamic(() => import('@/components/scene/astronautScene'), { ssr: false, }); export default function AboutUsSection() { + const topLineRef = useRef(null); + + useEffect(() => { + gsap.registerPlugin(ScrollTrigger); + + const observer = new IntersectionObserver( + (entries) => { + entries.forEach((entry) => { + if (entry.isIntersecting && entry.intersectionRatio >= 0.9) { + gsap.to(entry.target, { + opacity: 1, + y: 0, + duration: 1, + ease: 'power2.out', + scrollTrigger: { + trigger: entry.target, + start: 'top 5%', + end: 'bottom 100%', + scrub: true, + }, + }); + } + }); + }, + { + rootMargin: '0px', + threshold: 0.9, + } + ); + + if (topLineRef.current) { + gsap.set(topLineRef.current, { + opacity: 0, + y: 50, + }); + + observer.observe(topLineRef.current); + } + + return () => { + if (topLineRef.current) { + observer.unobserve(topLineRef.current); + } + }; + }, []); + return (
{/* Astronaut Scene */}
{/* Top line */} -
-
+
+
-
+
01
{/* Content */} -
-
-

+
+
+

FUTURE OF{' '} @@ -40,7 +93,7 @@ export default function AboutUsSection() {

Aerius Labs is where cryptography, blockchain, and zero-knowledge @@ -60,7 +113,7 @@ export default function AboutUsSection() {

{/* Bottom line */} -
+
bottomLineForSmallS_image -
+
02
+

); } diff --git a/src/components/section/aeriusLogoSection.tsx b/src/components/section/aeriusLogoSection.tsx index 3e21772..0ec864c 100644 --- a/src/components/section/aeriusLogoSection.tsx +++ b/src/components/section/aeriusLogoSection.tsx @@ -1,15 +1,54 @@ import dynamic from 'next/dynamic'; +import { useEffect } from 'react'; +import { gsap } from 'gsap'; +import { ScrollTrigger } from 'gsap/ScrollTrigger'; const Scene = dynamic(() => import('@/components/scene/aeriusLogoScene'), { ssr: false, }); +gsap.registerPlugin(ScrollTrigger); + export default function AeriusLogoSection() { + useEffect(() => { + const logoContainer = document.getElementById('logoContainer'); + + if (logoContainer) { + gsap.fromTo( + logoContainer, + { opacity: 0 }, + { + opacity: 1, + scrollTrigger: { + trigger: '#logoSection', + start: 'top center', + end: 'top top', + scrub: true, + }, + } + ); + } + + return () => ScrollTrigger.getAll().forEach((t) => t.kill()); + }, []); + return ( -
-
+
+
+
); } diff --git a/src/components/section/footerSection.tsx b/src/components/section/footerSection.tsx index f8a610c..c93736c 100644 --- a/src/components/section/footerSection.tsx +++ b/src/components/section/footerSection.tsx @@ -5,9 +5,9 @@ import { IBMPlexMono, FKScreamerBlack } from '@/fonts/fonts'; export default function FooterSection() { return ( -
-
-
+