| | |
| | |
| | |
| |
|
| |
|
| | class TerminalEffects {
|
| | constructor() {
|
| | this.isGlitching = false;
|
| | this.scanlineInterval = null;
|
| | this.init();
|
| | }
|
| |
|
| | init() {
|
| | this.createScanlines();
|
| | this.initCursorBlink();
|
| | this.initRandomGlitches();
|
| | this.initTypingEffects();
|
| | this.initMatrixRain();
|
| | }
|
| |
|
| |
|
| | createScanlines() {
|
| | const scanlines = document.createElement('div');
|
| | scanlines.className = 'scanlines';
|
| | scanlines.innerHTML = Array(50).fill().map((_, i) =>
|
| | `<div class="scanline" style="top: ${i * 2}%"></div>`
|
| | ).join('');
|
| |
|
| | const style = document.createElement('style');
|
| | style.textContent = `
|
| | .scanlines {
|
| | position: fixed;
|
| | top: 0;
|
| | left: 0;
|
| | right: 0;
|
| | bottom: 0;
|
| | pointer-events: none;
|
| | z-index: 1000;
|
| | opacity: 0.03;
|
| | }
|
| |
|
| | .scanline {
|
| | position: absolute;
|
| | left: 0;
|
| | right: 0;
|
| | height: 1px;
|
| | background: #39ff14;
|
| | animation: scanline-flicker 0.1s infinite alternate;
|
| | }
|
| |
|
| | @keyframes scanline-flicker {
|
| | 0% { opacity: 0.8; }
|
| | 100% { opacity: 0.2; }
|
| | }
|
| | `;
|
| |
|
| | document.head.appendChild(style);
|
| | document.body.appendChild(scanlines);
|
| | }
|
| |
|
| |
|
| | initCursorBlink() {
|
| | const cursors = document.querySelectorAll('.brand-cursor');
|
| | cursors.forEach(cursor => {
|
| | setInterval(() => {
|
| | cursor.style.opacity = cursor.style.opacity === '0' ? '1' : '0';
|
| | }, 500 + Math.random() * 200);
|
| | });
|
| | }
|
| |
|
| |
|
| | initRandomGlitches() {
|
| | setInterval(() => {
|
| | if (Math.random() < 0.02 && !this.isGlitching) {
|
| | this.triggerGlitch();
|
| | }
|
| | }, 1000);
|
| | }
|
| |
|
| | triggerGlitch() {
|
| | if (this.isGlitching) return;
|
| |
|
| | this.isGlitching = true;
|
| | const elements = document.querySelectorAll('.terminal-card, .chat-message');
|
| | const randomElement = elements[Math.floor(Math.random() * elements.length)];
|
| |
|
| | if (randomElement) {
|
| | const originalTransform = randomElement.style.transform;
|
| | const glitchIntensity = Math.random() * 5;
|
| |
|
| |
|
| | randomElement.style.filter = `hue-rotate(${Math.random() * 360}deg) saturate(2)`;
|
| | randomElement.style.transform = `translateX(${Math.random() * glitchIntensity - glitchIntensity/2}px) skew(${Math.random() * 2}deg)`;
|
| |
|
| |
|
| | randomElement.style.textShadow = `
|
| | ${Math.random() * 10 - 5}px 0 #ff0000,
|
| | ${Math.random() * 10 - 5}px 0 #00ff00,
|
| | ${Math.random() * 10 - 5}px 0 #0000ff
|
| | `;
|
| |
|
| | setTimeout(() => {
|
| | randomElement.style.filter = '';
|
| | randomElement.style.transform = originalTransform;
|
| | randomElement.style.textShadow = '';
|
| | this.isGlitching = false;
|
| | }, 50 + Math.random() * 100);
|
| | } else {
|
| | this.isGlitching = false;
|
| | }
|
| | }
|
| |
|
| |
|
| | typeWriter(element, text, speed = 50, callback = null) {
|
| | let i = 0;
|
| | element.textContent = '';
|
| |
|
| | const timer = setInterval(() => {
|
| | if (i < text.length) {
|
| | element.textContent += text.charAt(i);
|
| | i++;
|
| |
|
| |
|
| | if (Math.random() < 0.1) {
|
| | clearInterval(timer);
|
| | setTimeout(() => {
|
| | this.typeWriter(element, text.substring(i), speed, callback);
|
| | }, speed * 2);
|
| | return;
|
| | }
|
| | } else {
|
| | clearInterval(timer);
|
| | if (callback) callback();
|
| | }
|
| | }, speed);
|
| | }
|
| |
|
| | initTypingEffects() {
|
| |
|
| | const typeElements = document.querySelectorAll('.typewriter-effect');
|
| | typeElements.forEach(element => {
|
| | const text = element.textContent;
|
| | this.typeWriter(element, text, 30);
|
| | });
|
| | }
|
| |
|
| |
|
| | initMatrixRain() {
|
| | const canvas = document.createElement('canvas');
|
| | canvas.style.position = 'fixed';
|
| | canvas.style.top = '0';
|
| | canvas.style.left = '0';
|
| | canvas.style.width = '100%';
|
| | canvas.style.height = '100%';
|
| | canvas.style.pointerEvents = 'none';
|
| | canvas.style.zIndex = '-2';
|
| | canvas.style.opacity = '0.03';
|
| |
|
| | const ctx = canvas.getContext('2d');
|
| | canvas.width = window.innerWidth;
|
| | canvas.height = window.innerHeight;
|
| |
|
| | const matrix = "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789@#$%^&*()*&^%+-/~{[|`]}";
|
| | const matrixArray = matrix.split("");
|
| |
|
| | const fontSize = 10;
|
| | const columns = canvas.width / fontSize;
|
| | const drops = [];
|
| |
|
| | for (let x = 0; x < columns; x++) {
|
| | drops[x] = 1;
|
| | }
|
| |
|
| | function draw() {
|
| | ctx.fillStyle = 'rgba(13, 17, 23, 0.04)';
|
| | ctx.fillRect(0, 0, canvas.width, canvas.height);
|
| |
|
| | ctx.fillStyle = '#39ff14';
|
| | ctx.font = fontSize + 'px monospace';
|
| |
|
| | for (let i = 0; i < drops.length; i++) {
|
| | const text = matrixArray[Math.floor(Math.random() * matrixArray.length)];
|
| | ctx.fillText(text, i * fontSize, drops[i] * fontSize);
|
| |
|
| | if (drops[i] * fontSize > canvas.height && Math.random() > 0.975) {
|
| | drops[i] = 0;
|
| | }
|
| | drops[i]++;
|
| | }
|
| | }
|
| |
|
| | document.body.appendChild(canvas);
|
| | setInterval(draw, 150);
|
| |
|
| |
|
| | window.addEventListener('resize', () => {
|
| | canvas.width = window.innerWidth;
|
| | canvas.height = window.innerHeight;
|
| | });
|
| | }
|
| |
|
| |
|
| | powerOnEffect(element) {
|
| | element.style.opacity = '0';
|
| | element.style.transform = 'scale(0.8) rotateX(20deg)';
|
| | element.style.filter = 'brightness(0)';
|
| |
|
| | setTimeout(() => {
|
| | element.style.transition = 'all 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275)';
|
| | element.style.opacity = '1';
|
| | element.style.transform = 'scale(1) rotateX(0deg)';
|
| | element.style.filter = 'brightness(1)';
|
| |
|
| |
|
| | element.style.boxShadow = '0 0 20px var(--terminal-green-glow)';
|
| | setTimeout(() => {
|
| | element.style.boxShadow = '';
|
| | }, 500);
|
| | }, 100);
|
| | }
|
| |
|
| |
|
| | bootSequence(container, messages, onComplete) {
|
| | let messageIndex = 0;
|
| | const bootContainer = document.createElement('div');
|
| | bootContainer.className = 'boot-sequence';
|
| | bootContainer.innerHTML = `
|
| | <div class="terminal-window">
|
| | <div class="terminal-header">
|
| | <div class="terminal-dots">
|
| | <div class="terminal-dot red"></div>
|
| | <div class="terminal-dot yellow"></div>
|
| | <div class="terminal-dot green"></div>
|
| | </div>
|
| | <h6 class="terminal-title">system_boot.log</h6>
|
| | </div>
|
| | <div class="boot-content bg-dark p-3" style="font-family: var(--terminal-font); min-height: 200px;">
|
| | <div class="boot-messages"></div>
|
| | </div>
|
| | </div>
|
| | `;
|
| |
|
| | container.appendChild(bootContainer);
|
| | const messagesContainer = bootContainer.querySelector('.boot-messages');
|
| |
|
| | function addMessage() {
|
| | if (messageIndex < messages.length) {
|
| | const messageDiv = document.createElement('div');
|
| | messageDiv.className = 'text-terminal-green';
|
| | messageDiv.innerHTML = `<span class="text-muted">></span> ${messages[messageIndex]}`;
|
| | messagesContainer.appendChild(messageDiv);
|
| |
|
| |
|
| | messagesContainer.scrollTop = messagesContainer.scrollHeight;
|
| |
|
| | messageIndex++;
|
| | setTimeout(addMessage, 300 + Math.random() * 200);
|
| | } else {
|
| | setTimeout(() => {
|
| | container.removeChild(bootContainer);
|
| | if (onComplete) onComplete();
|
| | }, 1000);
|
| | }
|
| | }
|
| |
|
| | setTimeout(addMessage, 500);
|
| | }
|
| |
|
| |
|
| | showNetworkActivity() {
|
| | const indicator = document.querySelector('.status-indicator');
|
| | if (indicator) {
|
| | indicator.style.background = '#ffbd2e';
|
| | indicator.style.animation = 'pulse-glow 0.3s infinite';
|
| |
|
| | setTimeout(() => {
|
| | indicator.style.background = 'var(--terminal-green)';
|
| | indicator.style.animation = 'pulse-glow 2s infinite';
|
| | }, 1000);
|
| | }
|
| | }
|
| |
|
| |
|
| | errorFlash() {
|
| | document.body.style.backgroundColor = '#ff5f5610';
|
| | setTimeout(() => {
|
| | document.body.style.backgroundColor = '';
|
| | }, 150);
|
| | }
|
| |
|
| |
|
| | successFlash() {
|
| | document.body.style.backgroundColor = '#39ff1410';
|
| | setTimeout(() => {
|
| | document.body.style.backgroundColor = '';
|
| | }, 150);
|
| | }
|
| | }
|
| |
|
| |
|
| | document.addEventListener('DOMContentLoaded', () => {
|
| | window.terminalEffects = new TerminalEffects();
|
| | });
|
| |
|
| |
|
| | window.TerminalEffects = TerminalEffects; |