Enhance visual effects by adding shoe glow and horizon wave animations; increase ambient particle count for improved aesthetics.
This commit is contained in:
parent
734250524f
commit
5a8f0f2df9
@ -112,6 +112,21 @@ body {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
filter: drop-shadow(0 0 14px rgba(110, 165, 255, 0.8)) drop-shadow(0 0 36px rgba(70, 120, 255, 0.4));
|
filter: drop-shadow(0 0 14px rgba(110, 165, 255, 0.8)) drop-shadow(0 0 36px rgba(70, 120, 255, 0.4));
|
||||||
|
animation: shoeGlow 2s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes shoeGlow {
|
||||||
|
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
filter:
|
||||||
|
drop-shadow(rgba(110, 165, 255, 0.5) 0px 0px 10px) drop-shadow(rgba(70, 120, 255, 0.25) 0px 0px 25px);
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
filter:
|
||||||
|
drop-shadow(rgba(110, 165, 255, 1) 0px 0px 20px) drop-shadow(rgba(70, 120, 255, 0.65) 0px 0px 50px);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Outer layer: a plain rectangular clip that reveals left-to-right in
|
/* Outer layer: a plain rectangular clip that reveals left-to-right in
|
||||||
@ -158,10 +173,12 @@ body {
|
|||||||
top: 45%;
|
top: 45%;
|
||||||
height: 3px;
|
height: 3px;
|
||||||
margin-top: -1.5px;
|
margin-top: -1.5px;
|
||||||
|
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transform: scaleX(0);
|
transform: scaleX(0);
|
||||||
transform-origin: center;
|
transform-origin: center;
|
||||||
|
|
||||||
|
z-index: 3;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
|
||||||
border-top: 2px solid;
|
border-top: 2px solid;
|
||||||
@ -174,6 +191,55 @@ body {
|
|||||||
|
|
||||||
filter:
|
filter:
|
||||||
drop-shadow(0 0 4px rgba(255, 255, 255, 0.9)) drop-shadow(0 0 12px rgba(110, 165, 255, 0.8)) drop-shadow(0 0 30px rgba(70, 120, 255, 0.5));
|
drop-shadow(0 0 4px rgba(255, 255, 255, 0.9)) drop-shadow(0 0 12px rgba(110, 165, 255, 0.8)) drop-shadow(0 0 30px rgba(70, 120, 255, 0.5));
|
||||||
|
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Moving wave */
|
||||||
|
.shoe-stage__horizon::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: -2px;
|
||||||
|
left: -10%;
|
||||||
|
width: 20%;
|
||||||
|
height: 5px;
|
||||||
|
|
||||||
|
background: linear-gradient(90deg,
|
||||||
|
transparent,
|
||||||
|
rgba(255, 255, 255, 0.9),
|
||||||
|
rgba(110, 165, 255, 0.8),
|
||||||
|
transparent);
|
||||||
|
|
||||||
|
filter: blur(5px);
|
||||||
|
opacity: 0;
|
||||||
|
|
||||||
|
animation: horizonWave 2.5s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes horizonWave {
|
||||||
|
0% {
|
||||||
|
left: -10%;
|
||||||
|
opacity: 0;
|
||||||
|
transform: scaleY(0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
20% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
transform: scaleY(1.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
80% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
left: 90%;
|
||||||
|
opacity: 0;
|
||||||
|
transform: scaleY(0.5);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.shoe-stage__particles {
|
.shoe-stage__particles {
|
||||||
|
|||||||
@ -43,7 +43,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
|
|
||||||
/* ── Ambient dust: persistent, independent of the scroll timeline ── */
|
/* ── Ambient dust: persistent, independent of the scroll timeline ── */
|
||||||
const ambientHost = document.getElementById('ambientParticles');
|
const ambientHost = document.getElementById('ambientParticles');
|
||||||
const AMBIENT_COUNT = 22;
|
const AMBIENT_COUNT = 38;
|
||||||
for (let i = 0; i < AMBIENT_COUNT; i++) {
|
for (let i = 0; i < AMBIENT_COUNT; i++) {
|
||||||
const p = document.createElement('span');
|
const p = document.createElement('span');
|
||||||
p.className = 'ambient-particle';
|
p.className = 'ambient-particle';
|
||||||
@ -70,12 +70,14 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
gsap.set(treeSvg, { opacity: 1 });
|
gsap.set(treeSvg, { opacity: 1 });
|
||||||
gsap.set(branchGroups, { clipPath: 'inset(0% 0% 0% 0%)' });
|
gsap.set(branchGroups, { clipPath: 'inset(0% 0% 0% 0%)' });
|
||||||
gsap.set(nodes, { opacity: 1, scale: 1 });
|
gsap.set(nodes, { opacity: 1, scale: 1 });
|
||||||
|
gsap.set(routes, { opacity: 1, y: -4 });
|
||||||
routes.forEach((el) => el.classList.add('is-lit'));
|
routes.forEach((el) => el.classList.add('is-lit'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
gsap.set(shoeStage, { opacity: 0 });
|
gsap.set(shoeStage, { opacity: 0 });
|
||||||
gsap.set(labels, { opacity: 0, y: 10, scale: 0.9, transformOrigin: '50% 50%' });
|
gsap.set(labels, { opacity: 0, y: 10, scale: 0.9, transformOrigin: '50% 50%' });
|
||||||
|
gsap.set(routes, { opacity: 0, y: 20 });
|
||||||
|
|
||||||
function playIntro() {
|
function playIntro() {
|
||||||
const tl = gsap.timeline({ defaults: { ease: 'power2.out' } });
|
const tl = gsap.timeline({ defaults: { ease: 'power2.out' } });
|
||||||
@ -112,8 +114,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
|
|
||||||
// 6. The tree becomes visible, then each branch draws itself in
|
// 6. The tree becomes visible, then each branch draws itself in
|
||||||
// center-out: the middle line first, then the two adjacent, then
|
// center-out: the middle line first, then the two adjacent, then
|
||||||
// the two outer ones — each followed by its node flashing and
|
// the two outer ones — each followed by its node simply appearing
|
||||||
// its pill lighting up as the light "arrives".
|
// and its pill lighting up as the light "arrives".
|
||||||
const centerIndex = Math.floor(branchGroups.length / 2);
|
const centerIndex = Math.floor(branchGroups.length / 2);
|
||||||
const STEP = 0.22;
|
const STEP = 0.22;
|
||||||
const BRANCH_DUR = 0.9;
|
const BRANCH_DUR = 0.9;
|
||||||
@ -125,17 +127,26 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
const pos = `branches+=${(Math.abs(i - centerIndex) * STEP).toFixed(2)}`;
|
const pos = `branches+=${(Math.abs(i - centerIndex) * STEP).toFixed(2)}`;
|
||||||
tl.fromTo(group,
|
tl.fromTo(group,
|
||||||
{ clipPath: 'inset(0% 0% 100% 0%)' },
|
{ clipPath: 'inset(0% 0% 100% 0%)' },
|
||||||
{ clipPath: 'inset(0% 0% 0% 0%)', duration: BRANCH_DUR, ease: 'power2.out' },
|
{
|
||||||
|
clipPath: 'inset(0% 0% 0% 0%)',
|
||||||
|
duration: BRANCH_DUR,
|
||||||
|
ease: 'power2.out',
|
||||||
|
// Fires exactly when this branch's line finishes drawing, so
|
||||||
|
// the node and its route card never appear before the line
|
||||||
|
// has actually reached them.
|
||||||
|
onComplete: () => {
|
||||||
|
gsap.to(nodes[i], { opacity: 1, duration: 0.12 });
|
||||||
|
gsap.to(routes[i], {
|
||||||
|
opacity: 1,
|
||||||
|
y: -4, // matches .is-lit's lift so there's no transform conflict
|
||||||
|
duration: 0.4,
|
||||||
|
ease: 'power2.out',
|
||||||
|
onComplete: () => routes[i].classList.add('is-lit'),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
pos
|
pos
|
||||||
);
|
);
|
||||||
// Opacity reveal is permanent; the scale punch alone yoyos back down.
|
|
||||||
tl.to(nodes[i], { opacity: 1, duration: 0.15 }, `${pos}+=${BRANCH_DUR - 0.15}`);
|
|
||||||
tl.fromTo(nodes[i],
|
|
||||||
{ scale: 1 },
|
|
||||||
{ scale: 1.5, duration: 0.18, yoyo: true, repeat: 1, ease: 'power2.out' },
|
|
||||||
`${pos}+=${BRANCH_DUR - 0.15}`
|
|
||||||
);
|
|
||||||
tl.call(() => routes[i].classList.add('is-lit'), null, `${pos}+=${(BRANCH_DUR - 0.05).toFixed(2)}`);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return tl;
|
return tl;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user