version 1 with webshell and docs
This commit is contained in:
89
src/main.ts
Normal file
89
src/main.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import './style.css';
|
||||
|
||||
// Matrix rain effect
|
||||
const canvas = document.getElementById('matrix') as HTMLCanvasElement;
|
||||
const ctx = canvas.getContext('2d')!;
|
||||
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
|
||||
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789@#$%^&*()_+-=[]{}|;:,.<>?/~`';
|
||||
const fontSize = 14;
|
||||
const columns = canvas.width / fontSize;
|
||||
const drops: number[] = Array(Math.floor(columns)).fill(1);
|
||||
|
||||
let mouseX = canvas.width / 2;
|
||||
let mouseY = canvas.height / 2;
|
||||
|
||||
function draw() {
|
||||
ctx.fillStyle = 'rgba(0, 0, 0, 0.05)';
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
ctx.font = `${fontSize}px monospace`;
|
||||
|
||||
for (let i = 0; i < drops.length; i++) {
|
||||
const x = i * fontSize;
|
||||
const y = drops[i] * fontSize;
|
||||
const dist = Math.sqrt((x - mouseX) ** 2 + (y - mouseY) ** 2);
|
||||
|
||||
const text = chars[Math.floor(Math.random() * chars.length)];
|
||||
|
||||
// Only show characters near cursor
|
||||
const alpha = Math.max(0, 1 - dist / 250);
|
||||
|
||||
if (alpha > 0.1) {
|
||||
const color = dist < 120 ? '#a6e3a1' : dist < 200 ? '#89b4fa' : '#6c7086';
|
||||
ctx.fillStyle = color + Math.floor(alpha * 255).toString(16).padStart(2, '0');
|
||||
ctx.fillText(text, x, y);
|
||||
}
|
||||
|
||||
if (drops[i] * fontSize > canvas.height && Math.random() > 0.975) drops[i] = 0;
|
||||
drops[i]++;
|
||||
}
|
||||
}
|
||||
|
||||
setInterval(draw, 33);
|
||||
|
||||
window.addEventListener('mousemove', (e) => {
|
||||
mouseX = e.clientX;
|
||||
mouseY = e.clientY;
|
||||
});
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
});
|
||||
|
||||
// Copy functionality
|
||||
const commandBox = document.getElementById('commandBox') as HTMLDivElement;
|
||||
const copyBtn = document.getElementById('copyBtn') as HTMLButtonElement;
|
||||
const tooltip = document.getElementById('tooltip') as HTMLDivElement;
|
||||
const COMMAND = 'ssh portfolio@keshavanand.net';
|
||||
|
||||
async function copyToClipboard() {
|
||||
try {
|
||||
await navigator.clipboard.writeText(COMMAND);
|
||||
copyBtn.classList.add('copied');
|
||||
tooltip.classList.add('show');
|
||||
setTimeout(() => {
|
||||
copyBtn.classList.remove('copied');
|
||||
tooltip.classList.remove('show');
|
||||
}, 2000);
|
||||
} catch (err) {
|
||||
console.error('Failed to copy:', err);
|
||||
}
|
||||
}
|
||||
|
||||
copyBtn.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
copyToClipboard();
|
||||
});
|
||||
|
||||
commandBox.addEventListener('click', (e) => {
|
||||
if (!(e.target as HTMLElement).closest('.copy-btn')) copyToClipboard();
|
||||
});
|
||||
|
||||
// Fade in docs link after 2 seconds
|
||||
setTimeout(() => {
|
||||
document.getElementById('docsLink')?.classList.add('show');
|
||||
}, 2000);
|
||||
Reference in New Issue
Block a user