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%;
|
||||
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));
|
||||
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
|
||||
@ -158,10 +173,12 @@ body {
|
||||
top: 45%;
|
||||
height: 3px;
|
||||
margin-top: -1.5px;
|
||||
|
||||
opacity: 0;
|
||||
transform: scaleX(0);
|
||||
transform-origin: center;
|
||||
|
||||
z-index: 3;
|
||||
pointer-events: none;
|
||||
|
||||
border-top: 2px solid;
|
||||
@ -174,6 +191,55 @@ body {
|
||||
|
||||
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));
|
||||
|
||||
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 {
|
||||
|
||||
@ -43,7 +43,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
/* ── Ambient dust: persistent, independent of the scroll timeline ── */
|
||||
const ambientHost = document.getElementById('ambientParticles');
|
||||
const AMBIENT_COUNT = 22;
|
||||
const AMBIENT_COUNT = 38;
|
||||
for (let i = 0; i < AMBIENT_COUNT; i++) {
|
||||
const p = document.createElement('span');
|
||||
p.className = 'ambient-particle';
|
||||
@ -70,12 +70,14 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
gsap.set(treeSvg, { opacity: 1 });
|
||||
gsap.set(branchGroups, { clipPath: 'inset(0% 0% 0% 0%)' });
|
||||
gsap.set(nodes, { opacity: 1, scale: 1 });
|
||||
gsap.set(routes, { opacity: 1, y: -4 });
|
||||
routes.forEach((el) => el.classList.add('is-lit'));
|
||||
return;
|
||||
}
|
||||
|
||||
gsap.set(shoeStage, { opacity: 0 });
|
||||
gsap.set(labels, { opacity: 0, y: 10, scale: 0.9, transformOrigin: '50% 50%' });
|
||||
gsap.set(routes, { opacity: 0, y: 20 });
|
||||
|
||||
function playIntro() {
|
||||
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
|
||||
// center-out: the middle line first, then the two adjacent, then
|
||||
// the two outer ones — each followed by its node flashing and
|
||||
// its pill lighting up as the light "arrives".
|
||||
// the two outer ones — each followed by its node simply appearing
|
||||
// and its pill lighting up as the light "arrives".
|
||||
const centerIndex = Math.floor(branchGroups.length / 2);
|
||||
const STEP = 0.22;
|
||||
const BRANCH_DUR = 0.9;
|
||||
@ -125,17 +127,26 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
const pos = `branches+=${(Math.abs(i - centerIndex) * STEP).toFixed(2)}`;
|
||||
tl.fromTo(group,
|
||||
{ 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
|
||||
);
|
||||
// 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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user