mirror of
https://github.com/adam-benyekkou/my_portfolio.git
synced 2026-01-15 20:20:09 +00:00
Finished hero with text scramble on init and occasional glitching, changed header layout on mobile for better UX, finished minimal footer
This commit is contained in:
@@ -9,6 +9,7 @@ import { HoloVideoContainerComponent } from '../../shared/ui/holo-video-containe
|
||||
})
|
||||
export class HeroDisplayComponent implements OnInit, OnDestroy {
|
||||
displayText: string = '';
|
||||
nameText: string = '';
|
||||
|
||||
private messageQueue: string[] = [
|
||||
'Web Developer',
|
||||
@@ -17,8 +18,11 @@ export class HeroDisplayComponent implements OnInit, OnDestroy {
|
||||
];
|
||||
|
||||
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;
|
||||
|
||||
@@ -34,12 +38,57 @@ export class HeroDisplayComponent implements OnInit, OnDestroy {
|
||||
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;
|
||||
|
||||
@@ -52,7 +101,7 @@ export class HeroDisplayComponent implements OnInit, OnDestroy {
|
||||
output += firstMessage[i];
|
||||
}
|
||||
|
||||
// Add intense scrambling for upcoming letters (very fast scramble)
|
||||
// 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';
|
||||
@@ -62,12 +111,12 @@ export class HeroDisplayComponent implements OnInit, OnDestroy {
|
||||
|
||||
if (currentIndex < firstMessage.length) {
|
||||
currentIndex++;
|
||||
setTimeout(animateNextLetter, 35 + Math.random() * 25); // Much faster: 35-60ms
|
||||
setTimeout(animateNextLetter, 35 + Math.random() * 25);
|
||||
} else {
|
||||
// Mount animation complete, start normal cycle
|
||||
this.displayText = firstMessage;
|
||||
this.currentMessage = firstMessage;
|
||||
this.messageQueue.shift(); // Remove the first message since we used it
|
||||
this.messageQueue.shift();
|
||||
this.isInitialMount = false;
|
||||
|
||||
// Start the regular cycle after a short pause
|
||||
@@ -95,7 +144,7 @@ export class HeroDisplayComponent implements OnInit, OnDestroy {
|
||||
|
||||
this.processTimeout = setTimeout(() => {
|
||||
this.processQueue();
|
||||
}, 6000); // Reduced from 10000 to 6000 (faster rotation)
|
||||
}, 6000);
|
||||
}
|
||||
|
||||
private startScrambleAnimation(nextMessage: string): void {
|
||||
@@ -146,7 +195,6 @@ export class HeroDisplayComponent implements OnInit, OnDestroy {
|
||||
const probability = Math.random();
|
||||
|
||||
if (probability < 0.05) {
|
||||
// Reduced from 0.2 to 0.05
|
||||
const scrambledText = this.currentMessage
|
||||
.split('')
|
||||
.map(() => (Math.random() > 0.5 ? '0' : '1'))
|
||||
@@ -157,10 +205,8 @@ export class HeroDisplayComponent implements OnInit, OnDestroy {
|
||||
this.displayText = this.currentMessage;
|
||||
}, 25);
|
||||
} else if (probability < 0.15) {
|
||||
// Reduced from 0.5 to 0.15
|
||||
const textArray = this.currentMessage.split('');
|
||||
for (let i = 0; i < Math.floor(textArray.length * 0.2); i++) {
|
||||
// Reduced from 0.4 to 0.2
|
||||
const idx = Math.floor(Math.random() * textArray.length);
|
||||
textArray[idx] = Math.random() > 0.5 ? '0' : '1';
|
||||
}
|
||||
@@ -173,11 +219,9 @@ export class HeroDisplayComponent implements OnInit, OnDestroy {
|
||||
|
||||
const jitterProbability = Math.random();
|
||||
if (jitterProbability < 0.1) {
|
||||
// Reduced from 0.5 to 0.1
|
||||
setTimeout(() => {
|
||||
const textArray = this.displayText.split('');
|
||||
for (let i = 0; i < 2; i++) {
|
||||
// Reduced from 4 to 2 characters
|
||||
const idx = Math.floor(Math.random() * textArray.length);
|
||||
if (textArray[idx] === '0' || textArray[idx] === '1') {
|
||||
textArray[idx] = textArray[idx] === '0' ? '1' : '0';
|
||||
@@ -192,7 +236,64 @@ export class HeroDisplayComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
this.frameRequest = requestAnimationFrame(() => {
|
||||
setTimeout(() => this.glitchText(), Math.random() * 500); // Increased from 150 to 500
|
||||
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
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user