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;
|
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;
|
||||||
|
|
|
||||||
|
|
@ -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">
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue