feat: enhance landing component with transitioning lock for smoother animations; update styles for improved visual consistency

This commit is contained in:
bryancito1090 2026-09-08 10:40:24 -05:00
parent a6cadd10b8
commit 64657c3b18
3 changed files with 51 additions and 43 deletions

View File

@ -14,6 +14,12 @@
background-color: #121517; background-color: #121517;
} }
.landing-container.transitioning-lock {
overflow: hidden !important;
height: 100vh !important;
max-height: 100vh !important;
}
/* Header Minimalista Flotante */ /* Header Minimalista Flotante */
.zen-header { .zen-header {
position: fixed; position: fixed;
@ -542,11 +548,12 @@
position: fixed; position: fixed;
inset: 0; inset: 0;
z-index: 9999; z-index: 9999;
background: rgba(8, 10, 14, 0.88); background: rgba(8, 10, 14, 0.94);
backdrop-filter: blur(8px); backdrop-filter: blur(10px);
pointer-events: none; pointer-events: none;
opacity: 0; opacity: 0;
transition: opacity 0.16s cubic-bezier(0.16, 1, 0.3, 1); overflow: hidden;
transition: opacity 0.3s cubic-bezier(0.16, 1, 0.3, 1);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
@ -558,17 +565,6 @@
pointer-events: auto; pointer-events: auto;
} }
.curtain-scanline {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 2px;
background: linear-gradient(90deg, transparent, #c59b27, #38bdf8, transparent);
box-shadow: 0 0 10px #c59b27;
animation: scanlinePass 0.8s linear infinite;
}
.curtain-logo-wrapper { .curtain-logo-wrapper {
position: relative; position: relative;
display: flex; display: flex;
@ -576,29 +572,31 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
gap: 14px; gap: 14px;
animation: logoWrapperEnter 0.25s cubic-bezier(0.16, 1, 0.3, 1) both; animation: logoWrapperEnter 0.3s cubic-bezier(0.16, 1, 0.3, 1) both;
} }
.logo-glow-ring { .logo-glow-ring {
position: absolute; position: absolute;
top: 10px; top: 50%;
width: 90px; left: 50%;
height: 90px; transform: translate(-50%, -50%);
width: 120px;
height: 120px;
border-radius: 50%; border-radius: 50%;
background: radial-gradient(circle, rgba(197, 155, 39, 0.45) 0%, rgba(56, 189, 248, 0.18) 50%, transparent 70%); background: radial-gradient(circle, rgba(197, 155, 39, 0.5) 0%, rgba(56, 189, 248, 0.2) 50%, transparent 70%);
filter: blur(14px); filter: blur(16px);
animation: logoPulseGlow 1.2s ease-in-out infinite alternate; animation: logoPulseGlow 1.2s ease-in-out infinite alternate;
pointer-events: none; pointer-events: none;
} }
.logo-image-container { .logo-image-container {
position: relative; position: relative;
width: 68px; width: 78px;
height: 68px; height: 78px;
border-radius: 12px; border-radius: 14px;
overflow: hidden; overflow: hidden;
border: 1px solid rgba(197, 155, 39, 0.45); border: 1px solid rgba(197, 155, 39, 0.5);
box-shadow: 0 0 24px rgba(197, 155, 39, 0.3), 0 8px 32px rgba(0, 0, 0, 0.85); box-shadow: 0 0 28px rgba(197, 155, 39, 0.35), 0 8px 32px rgba(0, 0, 0, 0.85);
background: #000000; background: #000000;
display: flex; display: flex;
align-items: center; align-items: center;
@ -610,15 +608,15 @@
height: 100%; height: 100%;
object-fit: cover; object-fit: cover;
transform: scale(0.92); transform: scale(0.92);
animation: logoBreath 1.3s ease-in-out infinite alternate; animation: logoBreath 1.2s ease-in-out infinite alternate;
} }
.logo-shimmer-sweep { .logo-shimmer-sweep {
position: absolute; position: absolute;
inset: 0; inset: 0;
background: linear-gradient(110deg, transparent 25%, rgba(255, 255, 255, 0.4) 50%, transparent 75%); background: linear-gradient(110deg, transparent 25%, rgba(255, 255, 255, 0.45) 50%, transparent 75%);
transform: translateX(-100%); transform: translateX(-100%);
animation: logoShimmer 1.1s cubic-bezier(0.4, 0, 0.2, 1) infinite; animation: logoShimmer 1.0s cubic-bezier(0.4, 0, 0.2, 1) infinite;
pointer-events: none; pointer-events: none;
} }
@ -642,12 +640,6 @@
100% { transform: translateX(100%); } 100% { transform: translateX(100%); }
} }
@keyframes scanlinePass {
0% { transform: translateY(0); opacity: 0; }
50% { opacity: 1; }
100% { transform: translateY(100vh); opacity: 0; }
}
@media (max-width: 768px) { @media (max-width: 768px) {
.zen-header { .zen-header {
padding: 0 8px; padding: 0 8px;

View File

@ -1,4 +1,4 @@
<div class="landing-container"> <div class="landing-container" [class.transitioning-lock]="isCurtainVisible()">
<!-- Header Minimalista Flotante (Glassmorphism & Zen High-Contrast) --> <!-- Header Minimalista Flotante (Glassmorphism & Zen High-Contrast) -->
<header class="zen-header"> <header class="zen-header">
<button type="button" class="brand-block-btn" (click)="setSection('hero')" [attr.aria-label]="i18n.t().navHome"> <button type="button" class="brand-block-btn" (click)="setSection('hero')" [attr.aria-label]="i18n.t().navHome">
@ -120,7 +120,6 @@
[class.visible]="isCurtainVisible()" [class.visible]="isCurtainVisible()"
aria-hidden="true" aria-hidden="true"
> >
<div class="curtain-scanline"></div>
<div class="curtain-logo-wrapper"> <div class="curtain-logo-wrapper">
<div class="logo-glow-ring"></div> <div class="logo-glow-ring"></div>
<div class="logo-image-container"> <div class="logo-image-container">

View File

@ -109,9 +109,14 @@ export class LandingComponent implements OnInit, OnDestroy {
this.transitionTargetSection.set(section); this.transitionTargetSection.set(section);
this.isCurtainVisible.set(true); this.isCurtainVisible.set(true);
if (typeof document !== 'undefined') {
document.documentElement.style.overflow = 'hidden';
document.body.style.overflow = 'hidden';
}
if (this.transitionTimer) clearTimeout(this.transitionTimer); if (this.transitionTimer) clearTimeout(this.transitionTimer);
// Brief fade-curtain duration before switching section component // Initial phase: show curtain and animated logo
this.transitionTimer = setTimeout(() => { this.transitionTimer = setTimeout(() => {
if (section === 'hero') { if (section === 'hero') {
this.heroEntryPosition.set(entryPosition); this.heroEntryPosition.set(entryPosition);
@ -135,14 +140,18 @@ export class LandingComponent implements OnInit, OnDestroy {
} }
} }
// Smoothly hide curtain after DOM mount and scroll placement // Appreciate the animated logo for a full animation cycle before smoothly fading out
setTimeout(() => { setTimeout(() => {
this.isCurtainVisible.set(false); this.isCurtainVisible.set(false);
if (typeof document !== 'undefined') {
document.documentElement.style.overflow = '';
document.body.style.overflow = '';
}
setTimeout(() => { setTimeout(() => {
this.isTransitioning = false; this.isTransitioning = false;
}, 220); }, 300);
}, 120); }, 550);
}, 150); }, 220);
} }
private setupScrollTransitions(): void { private setupScrollTransitions(): void {
@ -153,7 +162,10 @@ export class LandingComponent implements OnInit, OnDestroy {
} }
private onWheel = (e: WheelEvent): void => { private onWheel = (e: WheelEvent): void => {
if (this.isTransitioning) return; if (this.isTransitioning || this.isCurtainVisible()) {
e.preventDefault();
return;
}
// Ignorar si el usuario está interactuando con un modal o scroll interno // Ignorar si el usuario está interactuando con un modal o scroll interno
const target = e.target as HTMLElement | null; const target = e.target as HTMLElement | null;
@ -189,6 +201,7 @@ export class LandingComponent implements OnInit, OnDestroy {
}; };
private onTouchStart = (e: TouchEvent): void => { private onTouchStart = (e: TouchEvent): void => {
if (this.isTransitioning || this.isCurtainVisible()) return;
if (e.touches.length > 0) { if (e.touches.length > 0) {
this.touchStartY = e.touches[0].clientY; this.touchStartY = e.touches[0].clientY;
this.touchStartX = e.touches[0].clientX; this.touchStartX = e.touches[0].clientX;
@ -196,7 +209,7 @@ export class LandingComponent implements OnInit, OnDestroy {
}; };
private onTouchEnd = (e: TouchEvent): void => { private onTouchEnd = (e: TouchEvent): void => {
if (this.isTransitioning || e.changedTouches.length === 0) return; if (this.isTransitioning || this.isCurtainVisible() || e.changedTouches.length === 0) return;
const target = e.target as HTMLElement | null; const target = e.target as HTMLElement | null;
if (target?.closest('.project-detail-overlay, .modal-scroll-area')) { if (target?.closest('.project-detail-overlay, .modal-scroll-area')) {
@ -282,6 +295,10 @@ export class LandingComponent implements OnInit, OnDestroy {
if (this.transitionTimer !== null) { if (this.transitionTimer !== null) {
clearTimeout(this.transitionTimer); clearTimeout(this.transitionTimer);
} }
if (typeof document !== 'undefined') {
document.documentElement.style.overflow = '';
document.body.style.overflow = '';
}
if (typeof window !== 'undefined') { if (typeof window !== 'undefined') {
window.removeEventListener('wheel', this.onWheel); window.removeEventListener('wheel', this.onWheel);
window.removeEventListener('touchstart', this.onTouchStart); window.removeEventListener('touchstart', this.onTouchStart);