|
1 | | -import React, { useRef, useEffect } from 'react'; |
| 1 | +import React, { useRef, useEffect, memo } from 'react'; |
2 | 2 |
|
3 | | -const DigitalRain = () => { |
| 3 | +const DigitalRain = memo(({ isActive }) => { |
4 | 4 | const canvasRef = useRef(null); |
5 | 5 |
|
6 | 6 | useEffect(() => { |
| 7 | + if (!isActive) return; |
| 8 | + |
7 | 9 | const canvas = canvasRef.current; |
8 | 10 | const ctx = canvas.getContext('2d'); |
| 11 | + let animationFrameId; |
| 12 | + |
| 13 | + const resizeCanvas = () => { |
| 14 | + canvas.width = window.innerWidth; |
| 15 | + canvas.height = window.innerHeight; |
| 16 | + }; |
9 | 17 |
|
10 | | - // Set canvas to full width and height of its container |
11 | | - canvas.width = canvas.offsetWidth; |
12 | | - canvas.height = canvas.offsetHeight; |
| 18 | + resizeCanvas(); |
| 19 | + window.addEventListener('resize', resizeCanvas); |
13 | 20 |
|
14 | | - const katakana = 'アァカサタナハマヤャラワガザダバパイィキシチニヒミリヰギジヂビピウゥクスツヌフムユュルグズブヅプエェケセテネヘメレヱゲゼデベペオォコソトノホモヨョロヲゴゾドボポヴッン'; |
| 21 | + const katakana = 'アァカサタナハマヤャラワガザダバパイィキシチニヒミリヰギジヂビピウゥクスツヌフムユュルグズブヅプエェケセテネヘメレヱゲゼデベペオォコソトノホモヨョロヲゴゾドボпоヴッン'; |
15 | 22 | const latin = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; |
16 | 23 | const nums = '0123456789'; |
17 | 24 | const alphabet = katakana + latin + nums; |
18 | 25 |
|
19 | 26 | const fontSize = 16; |
20 | 27 | const columns = canvas.width / fontSize; |
21 | | - const rainDrops = Array.from({ length: columns }).map(() => 1); |
22 | | - |
23 | | - let animationFrameId; |
| 28 | + const rainDrops = Array.from({ length: Math.ceil(columns) }).map(() => 1); |
24 | 29 | let frameCount = 0; |
25 | | - const slowdownFactor = 3; // Higher number = slower rain |
| 30 | + const slowdownFactor = 5; |
26 | 31 |
|
27 | 32 | const draw = () => { |
28 | | - ctx.fillStyle = 'rgba(21, 21, 21, 0.05)'; // Semi-transparent black for fading effect |
| 33 | + ctx.fillStyle = 'rgba(0, 0, 0, 0.05)'; |
29 | 34 | ctx.fillRect(0, 0, canvas.width, canvas.height); |
30 | | - |
31 | | - ctx.fillStyle = '#0F0'; // Green text |
| 35 | + ctx.fillStyle = 'rgba(0, 200, 0, 1.0)'; |
32 | 36 | ctx.font = `${fontSize}px monospace`; |
33 | 37 |
|
34 | 38 | frameCount++; |
| 39 | + if (frameCount % slowdownFactor === 0) { |
| 40 | + for (let i = 0; i < rainDrops.length; i++) { |
| 41 | + const text = alphabet.charAt(Math.floor(Math.random() * alphabet.length)); |
| 42 | + ctx.fillText(text, i * fontSize, rainDrops[i] * fontSize); |
35 | 43 |
|
36 | | - for (let i = 0; i < rainDrops.length; i++) { |
37 | | - const text = alphabet.charAt(Math.floor(Math.random() * alphabet.length)); |
38 | | - ctx.fillText(text, i * fontSize, rainDrops[i] * fontSize); |
39 | | - |
40 | | - if (frameCount % slowdownFactor === 0) { |
41 | 44 | if (rainDrops[i] * fontSize > canvas.height && Math.random() > 0.975) { |
42 | 45 | rainDrops[i] = 0; |
43 | 46 | } |
44 | 47 | rainDrops[i]++; |
45 | 48 | } |
46 | 49 | } |
| 50 | + |
| 51 | + // Add notification text in the bottom left |
| 52 | + const notificationText = "Alt+K to bring command palette"; |
| 53 | + const fezcode = "fezcode.com"; |
| 54 | + ctx.font = "16px monospace"; |
| 55 | + ctx.fillStyle = "rgba(0, 255, 0, 0.05)"; |
| 56 | + ctx.textAlign = "left"; |
| 57 | + ctx.fillText(notificationText, 20, canvas.height - 20); |
| 58 | + ctx.textAlign = "right"; |
| 59 | + ctx.fillText(fezcode, canvas.width - 20, canvas.height - 20); |
| 60 | + |
47 | 61 | animationFrameId = requestAnimationFrame(draw); |
48 | 62 | }; |
| 63 | + |
49 | 64 | draw(); |
| 65 | + |
50 | 66 | return () => { |
| 67 | + window.removeEventListener('resize', resizeCanvas); |
51 | 68 | cancelAnimationFrame(animationFrameId); |
| 69 | + ctx.clearRect(0, 0, canvas.width, canvas.height); |
52 | 70 | }; |
53 | | - }, []); |
| 71 | + }, [isActive]); |
| 72 | + |
| 73 | + if (!isActive) return null; |
54 | 74 |
|
55 | | - // Style for the canvas to fill the modal body |
56 | 75 | const canvasStyle = { |
57 | | - display: 'block', |
58 | | - width: '100%', |
59 | | - height: '60vh', // Make it tall inside the modal |
| 76 | + position: 'fixed', |
| 77 | + top: 0, |
| 78 | + left: 0, |
| 79 | + width: '100vw', |
| 80 | + height: '100vh', |
| 81 | + zIndex: 40, |
60 | 82 | }; |
61 | 83 |
|
62 | | - return ( |
63 | | - <canvas ref={canvasRef} style={canvasStyle}></canvas> |
64 | | - ); |
65 | | -}; |
| 84 | + return <canvas ref={canvasRef} style={canvasStyle}></canvas>; |
| 85 | +}); |
66 | 86 |
|
67 | 87 | export default DigitalRain; |
0 commit comments