From c4a14c6ec75ce159584b7b594ac9f6f4c4573c9c Mon Sep 17 00:00:00 2001 From: AdamBtech <60339324+AdamBtech@users.noreply.github.com> Date: Mon, 2 Jun 2025 10:17:31 +0200 Subject: [PATCH] Refactoring hero page into smaller components --- .../hero/hero-text/hero-text.component.css | 0 .../hero/hero-text/hero-text.component.html | 21 ++ .../hero/hero-text/hero-text.component.ts | 298 ++++++++++++++++++ src/app/pages/hero/hero.component.html | 26 +- src/app/pages/hero/hero.component.ts | 296 +---------------- 5 files changed, 325 insertions(+), 316 deletions(-) create mode 100644 src/app/pages/hero/hero-text/hero-text.component.css create mode 100644 src/app/pages/hero/hero-text/hero-text.component.html create mode 100644 src/app/pages/hero/hero-text/hero-text.component.ts diff --git a/src/app/pages/hero/hero-text/hero-text.component.css b/src/app/pages/hero/hero-text/hero-text.component.css new file mode 100644 index 0000000..e69de29 diff --git a/src/app/pages/hero/hero-text/hero-text.component.html b/src/app/pages/hero/hero-text/hero-text.component.html new file mode 100644 index 0000000..eda9f5f --- /dev/null +++ b/src/app/pages/hero/hero-text/hero-text.component.html @@ -0,0 +1,21 @@ +
+

+ {{ nameText }} +

+
+ +
+

+ {{ displayText }} +

diff --git a/src/app/pages/hero/hero-text/hero-text.component.ts b/src/app/pages/hero/hero-text/hero-text.component.ts new file mode 100644 index 0000000..c0355eb --- /dev/null +++ b/src/app/pages/hero/hero-text/hero-text.component.ts @@ -0,0 +1,298 @@ +import { Component, OnDestroy, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-hero-text', + imports: [], + templateUrl: './hero-text.component.html', + styleUrl: './hero-text.component.css', +}) +export class HeroTextComponent implements OnInit, OnDestroy { + displayText: string = ''; + nameText: string = ''; + + private messageQueue: string[] = [ + 'Web Developer', + 'Coding Enjoyer', + 'Software Artisan', + ]; + + private currentMessage: string = ''; + private currentName: string = 'ADAM\nBENYEKKOU'; + private isGlitching: boolean = false; + private isNameGlitching: boolean = false; + private frameRequest: number | null = null; + private nameFrameRequest: number | null = null; + private processTimeout: any = null; + private isInitialMount: boolean = true; + + ngOnInit(): void { + this.initialMountAnimation(); + } + + ngOnDestroy(): void { + this.cleanup(); + } + + private cleanup(): void { + if (this.frameRequest) { + cancelAnimationFrame(this.frameRequest); + } + if (this.nameFrameRequest) { + cancelAnimationFrame(this.nameFrameRequest); + } + if (this.processTimeout) { + clearTimeout(this.processTimeout); + } + } + + private initialMountAnimation(): void { + // Start both animations simultaneously + this.animateNameOnInit(); + this.animateDisplayTextOnInit(); + } + + private animateNameOnInit(): void { + const targetName = this.currentName; + let currentIndex = 0; + + const animateNextLetter = (): void => { + if (currentIndex <= targetName.length) { + let output = ''; + + // Build the confirmed part + for (let i = 0; i < currentIndex; i++) { + output += targetName[i]; + } + + // Add intense scrambling for upcoming letters + const scrambleLength = Math.min(8, targetName.length - currentIndex); + for (let i = 0; i < scrambleLength; i++) { + output += Math.random() > 0.5 ? '0' : '1'; + } + + this.nameText = output; + + if (currentIndex < targetName.length) { + currentIndex++; + setTimeout(animateNextLetter, 45 + Math.random() * 35); // Slightly slower for name + } else { + // Name animation complete, start glitching + this.nameText = targetName; + this.isNameGlitching = true; + this.glitchName(); + } + } + }; + + animateNextLetter(); + } + + private animateDisplayTextOnInit(): void { + const firstMessage = this.messageQueue[0]; + let currentIndex = 0; + + const animateNextLetter = (): void => { + if (currentIndex <= firstMessage.length) { + let output = ''; + + // Build the confirmed part + for (let i = 0; i < currentIndex; i++) { + output += firstMessage[i]; + } + + // Add intense scrambling for upcoming letters + const scrambleLength = Math.min(6, firstMessage.length - currentIndex); + for (let i = 0; i < scrambleLength; i++) { + output += Math.random() > 0.5 ? '0' : '1'; + } + + this.displayText = output; + + if (currentIndex < firstMessage.length) { + currentIndex++; + setTimeout(animateNextLetter, 35 + Math.random() * 25); + } else { + // Mount animation complete, start normal cycle + this.displayText = firstMessage; + this.currentMessage = firstMessage; + this.messageQueue.shift(); + this.isInitialMount = false; + + // Start the regular cycle after a short pause + setTimeout(() => { + this.processQueue(); + }, 2000); + } + } + }; + + animateNextLetter(); + } + + private processQueue(): void { + if (this.messageQueue.length === 0) { + this.messageQueue = [ + 'Web Developer', + 'Coding Enjoyer', + 'Software Artisan', + ]; + } + + const nextMessage = this.messageQueue.shift()!; + this.startScrambleAnimation(nextMessage); + + this.processTimeout = setTimeout(() => { + this.processQueue(); + }, 6000); + } + + private startScrambleAnimation(nextMessage: string): void { + const length = Math.max(this.displayText.length, nextMessage.length); + let complete = 0; + + const update = (): void => { + let output = ''; + const scrambleChars = 3 + Math.random() * 5; + + for (let i = 0; i < length; i++) { + const scramble = i < scrambleChars + complete && Math.random() > 0.8; + + if (i < nextMessage.length) { + if (scramble) { + output += Math.random() > 0.5 ? '0' : '1'; + } else if (i < complete) { + output += nextMessage[i]; + } else { + output += this.displayText[i] || (Math.random() > 0.5 ? '0' : '1'); + } + } + } + + this.displayText = output; + + if (complete < nextMessage.length) { + complete += 0.5 + Math.floor(Math.random() * 2); + setTimeout(update, 40 + Math.random() * 60); + } else { + this.displayText = nextMessage; + this.currentMessage = nextMessage; + this.isGlitching = true; + this.glitchText(); + } + }; + + this.isGlitching = false; + if (this.frameRequest) { + cancelAnimationFrame(this.frameRequest); + } + update(); + } + + private glitchText(): void { + if (!this.isGlitching) return; + + const probability = Math.random(); + + if (probability < 0.05) { + const scrambledText = this.currentMessage + .split('') + .map(() => (Math.random() > 0.5 ? '0' : '1')) + .join(''); + this.displayText = scrambledText; + + setTimeout(() => { + this.displayText = this.currentMessage; + }, 25); + } else if (probability < 0.15) { + const textArray = this.currentMessage.split(''); + for (let i = 0; i < Math.floor(textArray.length * 0.2); i++) { + const idx = Math.floor(Math.random() * textArray.length); + textArray[idx] = Math.random() > 0.5 ? '0' : '1'; + } + this.displayText = textArray.join(''); + + setTimeout(() => { + this.displayText = this.currentMessage; + }, 20); + } + + const jitterProbability = Math.random(); + if (jitterProbability < 0.1) { + setTimeout(() => { + const textArray = this.displayText.split(''); + for (let i = 0; i < 2; i++) { + const idx = Math.floor(Math.random() * textArray.length); + if (textArray[idx] === '0' || textArray[idx] === '1') { + textArray[idx] = textArray[idx] === '0' ? '1' : '0'; + } + } + this.displayText = textArray.join(''); + + setTimeout(() => { + this.displayText = this.currentMessage; + }, 15); + }, 15); + } + + this.frameRequest = requestAnimationFrame(() => { + setTimeout(() => this.glitchText(), Math.random() * 500); + }); + } + + private glitchName(): void { + if (!this.isNameGlitching) return; + + const probability = Math.random(); + + if (probability < 0.03) { + // Less frequent than displayText glitching + const scrambledName = this.currentName + .split('') + .map((char) => (char === '\n' ? '\n' : Math.random() > 0.5 ? '0' : '1')) + .join(''); + this.nameText = scrambledName; + + setTimeout(() => { + this.nameText = this.currentName; + }, 30); + } else if (probability < 0.08) { + const nameArray = this.currentName.split(''); + for (let i = 0; i < Math.floor(nameArray.length * 0.15); i++) { + const idx = Math.floor(Math.random() * nameArray.length); + if (nameArray[idx] !== '\n') { + // Don't replace line breaks + nameArray[idx] = Math.random() > 0.5 ? '0' : '1'; + } + } + this.nameText = nameArray.join(''); + + setTimeout(() => { + this.nameText = this.currentName; + }, 25); + } + + // Subtle character jitter + const jitterProbability = Math.random(); + if (jitterProbability < 0.05) { + setTimeout(() => { + const nameArray = this.nameText.split(''); + for (let i = 0; i < 1; i++) { + // Just 1 character at a time for name + const idx = Math.floor(Math.random() * nameArray.length); + if (nameArray[idx] === '0' || nameArray[idx] === '1') { + nameArray[idx] = nameArray[idx] === '0' ? '1' : '0'; + } + } + this.nameText = nameArray.join(''); + + setTimeout(() => { + this.nameText = this.currentName; + }, 20); + }, 20); + } + + this.nameFrameRequest = requestAnimationFrame(() => { + setTimeout(() => this.glitchName(), Math.random() * 800); // Slower glitching for name + }); + } +} diff --git a/src/app/pages/hero/hero.component.html b/src/app/pages/hero/hero.component.html index c55e5c7..34c0bc8 100644 --- a/src/app/pages/hero/hero.component.html +++ b/src/app/pages/hero/hero.component.html @@ -3,30 +3,8 @@ containerClasses="absolute inset-0 w-full h-full" videoSrc="video/cyber_hands.mp4" /> - +
- -
-

- {{ nameText }} -

-
- -
-

- {{ displayText }} -

-
+
diff --git a/src/app/pages/hero/hero.component.ts b/src/app/pages/hero/hero.component.ts index 3a346ce..4da59bd 100644 --- a/src/app/pages/hero/hero.component.ts +++ b/src/app/pages/hero/hero.component.ts @@ -1,299 +1,11 @@ -import { Component, OnInit, OnDestroy } from '@angular/core'; +import { Component } from '@angular/core'; import { HoloVideoContainerComponent } from '../../components/holo-video-container/holo-video-container.component'; +import { HeroTextComponent } from './hero-text/hero-text.component'; @Component({ selector: 'app-hero', - imports: [HoloVideoContainerComponent], + imports: [HoloVideoContainerComponent, HeroTextComponent], templateUrl: './hero.component.html', styleUrl: './hero.component.css', }) -export class HeroComponent implements OnInit, OnDestroy { - displayText: string = ''; - nameText: string = ''; - - private messageQueue: string[] = [ - 'Web Developer', - 'Coding Enjoyer', - 'Software Artisan', - ]; - - private currentMessage: string = ''; - private currentName: string = 'ADAM\nBENYEKKOU'; - private isGlitching: boolean = false; - private isNameGlitching: boolean = false; - private frameRequest: number | null = null; - private nameFrameRequest: number | null = null; - private processTimeout: any = null; - private isInitialMount: boolean = true; - - ngOnInit(): void { - this.initialMountAnimation(); - } - - ngOnDestroy(): void { - this.cleanup(); - } - - private cleanup(): void { - if (this.frameRequest) { - cancelAnimationFrame(this.frameRequest); - } - if (this.nameFrameRequest) { - cancelAnimationFrame(this.nameFrameRequest); - } - if (this.processTimeout) { - clearTimeout(this.processTimeout); - } - } - - private initialMountAnimation(): void { - // Start both animations simultaneously - this.animateNameOnInit(); - this.animateDisplayTextOnInit(); - } - - private animateNameOnInit(): void { - const targetName = this.currentName; - let currentIndex = 0; - - const animateNextLetter = (): void => { - if (currentIndex <= targetName.length) { - let output = ''; - - // Build the confirmed part - for (let i = 0; i < currentIndex; i++) { - output += targetName[i]; - } - - // Add intense scrambling for upcoming letters - const scrambleLength = Math.min(8, targetName.length - currentIndex); - for (let i = 0; i < scrambleLength; i++) { - output += Math.random() > 0.5 ? '0' : '1'; - } - - this.nameText = output; - - if (currentIndex < targetName.length) { - currentIndex++; - setTimeout(animateNextLetter, 45 + Math.random() * 35); // Slightly slower for name - } else { - // Name animation complete, start glitching - this.nameText = targetName; - this.isNameGlitching = true; - this.glitchName(); - } - } - }; - - animateNextLetter(); - } - - private animateDisplayTextOnInit(): void { - const firstMessage = this.messageQueue[0]; - let currentIndex = 0; - - const animateNextLetter = (): void => { - if (currentIndex <= firstMessage.length) { - let output = ''; - - // Build the confirmed part - for (let i = 0; i < currentIndex; i++) { - output += firstMessage[i]; - } - - // Add intense scrambling for upcoming letters - const scrambleLength = Math.min(6, firstMessage.length - currentIndex); - for (let i = 0; i < scrambleLength; i++) { - output += Math.random() > 0.5 ? '0' : '1'; - } - - this.displayText = output; - - if (currentIndex < firstMessage.length) { - currentIndex++; - setTimeout(animateNextLetter, 35 + Math.random() * 25); - } else { - // Mount animation complete, start normal cycle - this.displayText = firstMessage; - this.currentMessage = firstMessage; - this.messageQueue.shift(); - this.isInitialMount = false; - - // Start the regular cycle after a short pause - setTimeout(() => { - this.processQueue(); - }, 2000); - } - } - }; - - animateNextLetter(); - } - - private processQueue(): void { - if (this.messageQueue.length === 0) { - this.messageQueue = [ - 'Web Developer', - 'Coding Enjoyer', - 'Software Artisan', - ]; - } - - const nextMessage = this.messageQueue.shift()!; - this.startScrambleAnimation(nextMessage); - - this.processTimeout = setTimeout(() => { - this.processQueue(); - }, 6000); - } - - private startScrambleAnimation(nextMessage: string): void { - const length = Math.max(this.displayText.length, nextMessage.length); - let complete = 0; - - const update = (): void => { - let output = ''; - const scrambleChars = 3 + Math.random() * 5; - - for (let i = 0; i < length; i++) { - const scramble = i < scrambleChars + complete && Math.random() > 0.8; - - if (i < nextMessage.length) { - if (scramble) { - output += Math.random() > 0.5 ? '0' : '1'; - } else if (i < complete) { - output += nextMessage[i]; - } else { - output += this.displayText[i] || (Math.random() > 0.5 ? '0' : '1'); - } - } - } - - this.displayText = output; - - if (complete < nextMessage.length) { - complete += 0.5 + Math.floor(Math.random() * 2); - setTimeout(update, 40 + Math.random() * 60); - } else { - this.displayText = nextMessage; - this.currentMessage = nextMessage; - this.isGlitching = true; - this.glitchText(); - } - }; - - this.isGlitching = false; - if (this.frameRequest) { - cancelAnimationFrame(this.frameRequest); - } - update(); - } - - private glitchText(): void { - if (!this.isGlitching) return; - - const probability = Math.random(); - - if (probability < 0.05) { - const scrambledText = this.currentMessage - .split('') - .map(() => (Math.random() > 0.5 ? '0' : '1')) - .join(''); - this.displayText = scrambledText; - - setTimeout(() => { - this.displayText = this.currentMessage; - }, 25); - } else if (probability < 0.15) { - const textArray = this.currentMessage.split(''); - for (let i = 0; i < Math.floor(textArray.length * 0.2); i++) { - const idx = Math.floor(Math.random() * textArray.length); - textArray[idx] = Math.random() > 0.5 ? '0' : '1'; - } - this.displayText = textArray.join(''); - - setTimeout(() => { - this.displayText = this.currentMessage; - }, 20); - } - - const jitterProbability = Math.random(); - if (jitterProbability < 0.1) { - setTimeout(() => { - const textArray = this.displayText.split(''); - for (let i = 0; i < 2; i++) { - const idx = Math.floor(Math.random() * textArray.length); - if (textArray[idx] === '0' || textArray[idx] === '1') { - textArray[idx] = textArray[idx] === '0' ? '1' : '0'; - } - } - this.displayText = textArray.join(''); - - setTimeout(() => { - this.displayText = this.currentMessage; - }, 15); - }, 15); - } - - this.frameRequest = requestAnimationFrame(() => { - setTimeout(() => this.glitchText(), Math.random() * 500); - }); - } - - private glitchName(): void { - if (!this.isNameGlitching) return; - - const probability = Math.random(); - - if (probability < 0.03) { - // Less frequent than displayText glitching - const scrambledName = this.currentName - .split('') - .map((char) => (char === '\n' ? '\n' : Math.random() > 0.5 ? '0' : '1')) - .join(''); - this.nameText = scrambledName; - - setTimeout(() => { - this.nameText = this.currentName; - }, 30); - } else if (probability < 0.08) { - const nameArray = this.currentName.split(''); - for (let i = 0; i < Math.floor(nameArray.length * 0.15); i++) { - const idx = Math.floor(Math.random() * nameArray.length); - if (nameArray[idx] !== '\n') { - // Don't replace line breaks - nameArray[idx] = Math.random() > 0.5 ? '0' : '1'; - } - } - this.nameText = nameArray.join(''); - - setTimeout(() => { - this.nameText = this.currentName; - }, 25); - } - - // Subtle character jitter - const jitterProbability = Math.random(); - if (jitterProbability < 0.05) { - setTimeout(() => { - const nameArray = this.nameText.split(''); - for (let i = 0; i < 1; i++) { - // Just 1 character at a time for name - const idx = Math.floor(Math.random() * nameArray.length); - if (nameArray[idx] === '0' || nameArray[idx] === '1') { - nameArray[idx] = nameArray[idx] === '0' ? '1' : '0'; - } - } - this.nameText = nameArray.join(''); - - setTimeout(() => { - this.nameText = this.currentName; - }, 20); - }, 20); - } - - this.nameFrameRequest = requestAnimationFrame(() => { - setTimeout(() => this.glitchName(), Math.random() * 800); // Slower glitching for name - }); - } -} +export class HeroComponent {}