111 lines
3.3 KiB
TypeScript
111 lines
3.3 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useRef } from "react";
|
|
|
|
export default function MatrixBackground({
|
|
isSecure,
|
|
theme,
|
|
}: {
|
|
isSecure: boolean;
|
|
theme?: string;
|
|
}) {
|
|
const canvasRef = useRef<HTMLCanvasElement>(null);
|
|
|
|
useEffect(() => {
|
|
const canvas = canvasRef.current;
|
|
if (!canvas) return;
|
|
const ctx = canvas.getContext("2d");
|
|
if (!ctx) return;
|
|
|
|
let width = (canvas.width = window.innerWidth);
|
|
let height = (canvas.height = window.innerHeight);
|
|
|
|
const fontSize = 16;
|
|
const columns = Math.floor(width / fontSize);
|
|
const drops = Array(columns).fill(1);
|
|
|
|
const isDark = theme === "dark";
|
|
|
|
const draw = () => {
|
|
// Контрастный фон: в темной теме делаем глубокий черный
|
|
ctx.fillStyle = isDark
|
|
? "rgba(0, 0, 0, 0.08)" // Чистый черный для контраста
|
|
: "rgba(250, 250, 250, 0.05)";
|
|
ctx.fillRect(0, 0, width, height);
|
|
|
|
const gradient = ctx.createRadialGradient(
|
|
width / 2,
|
|
height / 2,
|
|
0,
|
|
width / 2,
|
|
height / 2,
|
|
Math.sqrt(width ** 2 + height ** 2) / 2,
|
|
);
|
|
|
|
if (isSecure) {
|
|
if (isDark) {
|
|
gradient.addColorStop(0, "#00F0FF"); // Центр: Ядовитый циановый
|
|
gradient.addColorStop(0.4, "#0080FF");
|
|
gradient.addColorStop(1, "rgba(0, 20, 40, 0)"); // Края уходят в прозрачность
|
|
} else {
|
|
gradient.addColorStop(0, "rgba(2, 132, 199, 1)");
|
|
gradient.addColorStop(1, "rgba(2, 85, 199, 0.2)");
|
|
}
|
|
} else {
|
|
if (isDark) {
|
|
gradient.addColorStop(0, "#7000FF"); // Центр: Яркий фиолетовый
|
|
gradient.addColorStop(0.4, "#400099");
|
|
gradient.addColorStop(1, "rgba(20, 0, 40, 0)");
|
|
} else {
|
|
gradient.addColorStop(0, "rgba(217, 40, 217, 1)");
|
|
gradient.addColorStop(1, "rgba(61, 40, 217, 0.2)");
|
|
}
|
|
}
|
|
|
|
ctx.fillStyle = gradient;
|
|
ctx.font = `bold ${fontSize}px monospace`; // Сделали шрифт bold для четкости
|
|
|
|
// Добавляем эффект свечения только для темной темы
|
|
if (isDark) {
|
|
ctx.shadowBlur = 8;
|
|
ctx.shadowColor = isSecure ? "#00F0FF" : "#7000FF";
|
|
} else {
|
|
ctx.shadowBlur = 0;
|
|
}
|
|
|
|
for (let i = 0; i < drops.length; i++) {
|
|
const text = Math.random() > 0.5 ? "1" : "0";
|
|
ctx.fillText(text, i * fontSize, drops[i] * fontSize);
|
|
|
|
if (drops[i] * fontSize > height && Math.random() > 0.975) {
|
|
drops[i] = 0;
|
|
}
|
|
drops[i]++;
|
|
}
|
|
};
|
|
|
|
const interval = setInterval(draw, 33);
|
|
|
|
const handleResize = () => {
|
|
width = canvas.width = window.innerWidth;
|
|
height = canvas.height = window.innerHeight;
|
|
};
|
|
window.addEventListener("resize", handleResize);
|
|
|
|
return () => {
|
|
clearInterval(interval);
|
|
window.removeEventListener("resize", handleResize);
|
|
};
|
|
}, [isSecure, theme]);
|
|
|
|
return (
|
|
<canvas
|
|
ref={canvasRef}
|
|
// opacity-100 для темной темы, чтобы не гасить яркость, и opacity-30 для светлой
|
|
className={`absolute inset-0 -z-20 transition-opacity duration-1000 ${
|
|
theme === "dark" ? "opacity-100" : "opacity-30"
|
|
}`}
|
|
/>
|
|
);
|
|
}
|