feat: enhance landing component with transitioning lock for smoother animations; update styles for improved visual consistency
This commit is contained in:
parent
a6cadd10b8
commit
64657c3b18
|
|
@ -14,6 +14,12 @@
|
|||
background-color: #121517;
|
||||
}
|
||||
|
||||
.landing-container.transitioning-lock {
|
||||
overflow: hidden !important;
|
||||
height: 100vh !important;
|
||||
max-height: 100vh !important;
|
||||
}
|
||||
|
||||
/* Header Minimalista Flotante */
|
||||
.zen-header {
|
||||
position: fixed;
|
||||
|
|
@ -542,11 +548,12 @@
|
|||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 9999;
|
||||
background: rgba(8, 10, 14, 0.88);
|
||||
backdrop-filter: blur(8px);
|
||||
background: rgba(8, 10, 14, 0.94);
|
||||
backdrop-filter: blur(10px);
|
||||
pointer-events: none;
|
||||
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;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
|
@ -558,17 +565,6 @@
|
|||
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 {
|
||||
position: relative;
|
||||
display: flex;
|
||||
|
|
@ -576,29 +572,31 @@
|
|||
align-items: center;
|
||||
justify-content: center;
|
||||
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 {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(circle, rgba(197, 155, 39, 0.45) 0%, rgba(56, 189, 248, 0.18) 50%, transparent 70%);
|
||||
filter: blur(14px);
|
||||
background: radial-gradient(circle, rgba(197, 155, 39, 0.5) 0%, rgba(56, 189, 248, 0.2) 50%, transparent 70%);
|
||||
filter: blur(16px);
|
||||
animation: logoPulseGlow 1.2s ease-in-out infinite alternate;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.logo-image-container {
|
||||
position: relative;
|
||||
width: 68px;
|
||||
height: 68px;
|
||||
border-radius: 12px;
|
||||
width: 78px;
|
||||
height: 78px;
|
||||
border-radius: 14px;
|
||||
overflow: hidden;
|
||||
border: 1px solid rgba(197, 155, 39, 0.45);
|
||||
box-shadow: 0 0 24px rgba(197, 155, 39, 0.3), 0 8px 32px rgba(0, 0, 0, 0.85);
|
||||
border: 1px solid rgba(197, 155, 39, 0.5);
|
||||
box-shadow: 0 0 28px rgba(197, 155, 39, 0.35), 0 8px 32px rgba(0, 0, 0, 0.85);
|
||||
background: #000000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
@ -610,15 +608,15 @@
|
|||
height: 100%;
|
||||
object-fit: cover;
|
||||
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 {
|
||||
position: absolute;
|
||||
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%);
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -642,12 +640,6 @@
|
|||
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) {
|
||||
.zen-header {
|
||||
padding: 0 8px;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<div class="landing-container">
|
||||
<div class="landing-container" [class.transitioning-lock]="isCurtainVisible()">
|
||||
<!-- Header Minimalista Flotante (Glassmorphism & Zen High-Contrast) -->
|
||||
<header class="zen-header">
|
||||
<button type="button" class="brand-block-btn" (click)="setSection('hero')" [attr.aria-label]="i18n.t().navHome">
|
||||
|
|
@ -120,7 +120,6 @@
|
|||
[class.visible]="isCurtainVisible()"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div class="curtain-scanline"></div>
|
||||
<div class="curtain-logo-wrapper">
|
||||
<div class="logo-glow-ring"></div>
|
||||
<div class="logo-image-container">
|
||||
|
|
|
|||
|
|
@ -109,9 +109,14 @@ export class LandingComponent implements OnInit, OnDestroy {
|
|||
this.transitionTargetSection.set(section);
|
||||
this.isCurtainVisible.set(true);
|
||||
|
||||
if (typeof document !== 'undefined') {
|
||||
document.documentElement.style.overflow = 'hidden';
|
||||
document.body.style.overflow = 'hidden';
|
||||
}
|
||||
|
||||
if (this.transitionTimer) clearTimeout(this.transitionTimer);
|
||||
|
||||
// Brief fade-curtain duration before switching section component
|
||||
// Initial phase: show curtain and animated logo
|
||||
this.transitionTimer = setTimeout(() => {
|
||||
if (section === 'hero') {
|
||||
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(() => {
|
||||
this.isCurtainVisible.set(false);
|
||||
if (typeof document !== 'undefined') {
|
||||
document.documentElement.style.overflow = '';
|
||||
document.body.style.overflow = '';
|
||||
}
|
||||
setTimeout(() => {
|
||||
this.isTransitioning = false;
|
||||
}, 220);
|
||||
}, 120);
|
||||
}, 150);
|
||||
}, 300);
|
||||
}, 550);
|
||||
}, 220);
|
||||
}
|
||||
|
||||
private setupScrollTransitions(): void {
|
||||
|
|
@ -153,7 +162,10 @@ export class LandingComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
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
|
||||
const target = e.target as HTMLElement | null;
|
||||
|
|
@ -189,6 +201,7 @@ export class LandingComponent implements OnInit, OnDestroy {
|
|||
};
|
||||
|
||||
private onTouchStart = (e: TouchEvent): void => {
|
||||
if (this.isTransitioning || this.isCurtainVisible()) return;
|
||||
if (e.touches.length > 0) {
|
||||
this.touchStartY = e.touches[0].clientY;
|
||||
this.touchStartX = e.touches[0].clientX;
|
||||
|
|
@ -196,7 +209,7 @@ export class LandingComponent implements OnInit, OnDestroy {
|
|||
};
|
||||
|
||||
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;
|
||||
if (target?.closest('.project-detail-overlay, .modal-scroll-area')) {
|
||||
|
|
@ -282,6 +295,10 @@ export class LandingComponent implements OnInit, OnDestroy {
|
|||
if (this.transitionTimer !== null) {
|
||||
clearTimeout(this.transitionTimer);
|
||||
}
|
||||
if (typeof document !== 'undefined') {
|
||||
document.documentElement.style.overflow = '';
|
||||
document.body.style.overflow = '';
|
||||
}
|
||||
if (typeof window !== 'undefined') {
|
||||
window.removeEventListener('wheel', this.onWheel);
|
||||
window.removeEventListener('touchstart', this.onTouchStart);
|
||||
|
|
|
|||
Loading…
Reference in New Issue