diff --git a/src/js/introAnimation.js b/src/js/introAnimation.js new file mode 100644 index 0000000..4e225f6 --- /dev/null +++ b/src/js/introAnimation.js @@ -0,0 +1,61 @@ +import { gsap } from "gsap"; + +const BLOB_ENTER = 2; + +const blobFront = { scale: 1.5, opacity: 0.65, filter: "blur(20px)", duration: 8, ease: "sine.inOut" }; +const blobBack = { scale: 0.6, opacity: 0.25, filter: "blur(52px)", duration: 8, ease: "sine.inOut" }; + +function randomBlob(selector, frontOverrides, delay) { + const rand = (min, max) => gsap.utils.random(min, max); + const isMo = () => window.innerWidth <= 768; + + function cycle() { + const xRange = isMo() ? 60 : 180; + const yRange = isMo() ? 140 : 100; + const x = rand(-xRange, xRange); + const y = rand(-yRange, yRange); + + gsap.timeline() + .to(selector, { ...blobFront, ...frontOverrides, x, y }) + .to(selector, { duration: 20 }) + .to(selector, { ...blobBack, x: 0, y: 0 }) + .call(cycle); + } + + gsap.delayedCall(delay, cycle); +} + +function morphBlob(selector, targetRadius, duration) { + gsap.to(selector, { + borderRadius: targetRadius, + duration, + repeat: -1, + yoyo: true, + ease: "sine.inOut", + }); +} + +export function initIntroAnimation() { + gsap.set([".blobCyan", ".blobPurple", ".blobBlue"], { + opacity: 0, + scale: 0.4, + filter: "blur(60px)", + }); + + gsap.to(".blobCyan", { opacity: 0.25, scale: 0.6, filter: "blur(50px)", duration: 1.6, ease: "power2.out" }); + gsap.to(".blobPurple", { opacity: 0.2, scale: 0.6, filter: "blur(55px)", duration: 1.6, ease: "power2.out", delay: 0.35 }); + gsap.to(".blobBlue", { opacity: 0.2, scale: 0.6, filter: "blur(55px)", duration: 1.6, ease: "power2.out", delay: 0.7 }); + + // 텍스트 순차 등장 + gsap.set([".intro__sub", ".intro__title"], { opacity: 0, y: 30 }); + gsap.to(".intro__sub", { opacity: 1, y: 0, duration: 0.9, ease: "power3.out", delay: 1.0 }); + gsap.to(".intro__title", { opacity: 1, y: 0, duration: 0.9, ease: "power3.out", delay: 1.3 }); + + randomBlob(".blobCyan", { opacity: 0.65, filter: "blur(20px)" }, BLOB_ENTER); + randomBlob(".blobPurple", { opacity: 0.55, filter: "blur(22px)" }, BLOB_ENTER + 6); + randomBlob(".blobBlue", { opacity: 0.55, filter: "blur(22px)" }, BLOB_ENTER + 12); + + morphBlob(".blobCyan", "60% 40% 55% 45% / 45% 60% 40% 55%", 1.8); + morphBlob(".blobPurple", "45% 55% 40% 60% / 60% 40% 55% 45%", 2.4); + morphBlob(".blobBlue", "55% 45% 60% 40% / 40% 60% 45% 55%", 2.1); +} diff --git a/src/js/main.js b/src/js/main.js index 4beae4f..ac685b8 100644 --- a/src/js/main.js +++ b/src/js/main.js @@ -1,9 +1,12 @@ import $ from "jquery"; import { gsap } from "gsap"; import { ScrollTrigger } from "gsap/ScrollTrigger"; +import { initIntroAnimation } from "./introAnimation.js"; gsap.registerPlugin(ScrollTrigger); +initIntroAnimation(); + $(function () { const $gnb = $("#gnb"); const $hamburger = $(".gnb__hamburger"); diff --git a/src/scss/page/_intro.scss b/src/scss/page/_intro.scss index b628793..8872f5a 100644 --- a/src/scss/page/_intro.scss +++ b/src/scss/page/_intro.scss @@ -20,8 +20,6 @@ .blob { position: absolute; border-radius: 50%; - filter: blur(60px); - opacity: 0.5; } .blobCyan { @@ -34,19 +32,19 @@ } .blobPurple { - width: 10vw; - height: 10vw; + width: 14vw; + height: 14vw; background: $color-purple; - top: 40%; - left: 50%; + top: 38%; + left: 46%; } .blobBlue { - width: 10vw; - height: 10vw; + width: 14vw; + height: 14vw; background: $color-blue; top: 42%; - left: 30%; + left: 28%; } } @@ -66,9 +64,9 @@ } .intro__title { - font-size: clamp(14px, 1.5vw, 20px); - font-weight: 900; - letter-spacing: 0.2em; + font-size: clamp(12px, 1.5vw, 20px); + font-weight: 700; + letter-spacing: 0.03em; text-transform: uppercase; color: $color-white; } @@ -92,23 +90,24 @@ } .blobCyan { - width: 90vw; - height: 90vw; + width: 80vw; + height: 80vw; right: -20%; top: -5%; } .blobPurple { - width: 60vw; - height: 60vw; + width: 65vw; + height: 65vw; left: -15%; - top: 20%; + top: 38%; + transform: translateY(-50%); } .blobBlue { - width: 50vw; - height: 50vw; - left: -10%; - bottom: 5%; + width: 70vw; + height: 70vw; + right: -15%; + bottom: -5%; } }