代码雨(第3版)edit icon

Fork(复制)
下载
嵌入
设置
BUG反馈
index.html
现在支持上传本地图片了!
            
            <!DOCTYPE html>
<html>
<head>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            overflow: hidden;
            background: #000;
            font-family: 'Courier New', monospace;
        }

        #matrix-canvas {
            position: fixed;
            top: 0;
            left: 0;
            z-index: 1;
        }

        .grid-overlay {
            position: fixed;
            top: 0;
            left: 0;
            width: 100vw;
            height: 100vh;
            background-image: 
                linear-gradient(to right, rgba(0, 255, 0, 0.05) 1px, transparent 1px),
                linear-gradient(to bottom, rgba(0, 255, 0, 0.05) 1px, transparent 1px);
            background-size: min(3vw, 40px) min(3vh, 40px);
            pointer-events: none;
            z-index: 2;
        }

        .status-text {
            position: fixed;
            bottom: 5vh;
            right: 5vw;
            color: #0f0;
            font-size: clamp(12px, 1.5vw, 18px);
            opacity: 1.5;
        }
    </style>
</head>
<body>
    <canvas id="matrix-canvas"></canvas>
    <div class="grid-overlay"></div>
    <div class="status-text" id="fps-counter">FPS: 60</div>

    <script>
        class MatrixSystem {
            constructor() {
                this.canvas = document.getElementById('matrix-canvas');
                this.ctx = this.canvas.getContext('2d');
                this.resizeObserver = new ResizeObserver(this.handleResize.bind(this));
                this.animationFrame = null;
                this.lastFrameTime = 0;
                this.fps = 60;
                this.drops = []; // 确保初始化为空数组

                this.init();
            }

            init() {
                
                this.handleResize([{ contentRect: { width: window.innerWidth, height: window.innerHeight } }]);
                
                
                this.resizeObserver.observe(document.documentElement);
                
                // 性能监控
                setInterval(() => {
                    document.getElementById('fps-counter').textContent = `FPS: ${Math.round(this.fps)}`;
                }, 1000);

                // 启动动画循环
                this.animate();
            }

            handleResize(entries) {
                const entry = entries[0] || { contentRect: { width: window.innerWidth, height: window.innerHeight } };
                const { width, height } = entry.contentRect;
                this.setCanvasSize(width, height);
                this.initMatrix();
            }

            setCanvasSize(w, h) {
                if(w <= 0 || h <= 0) return; // 防止无效尺寸
                
                this.canvas.width = w * devicePixelRatio;
                this.canvas.height = h * devicePixelRatio;
                this.canvas.style.width = `${w}px`;
                this.canvas.style.height = `${h}px`;
                this.ctx.scale(devicePixelRatio, devicePixelRatio);
            }

            initMatrix() {
                // 安全参数计算
                this.charSet = '喵喵喵';
                this.fontSize = Math.max(10, Math.min(window.innerWidth / 80, 20)); // 确保最小10px
                this.columns = Math.max(1, Math.floor(window.innerWidth / this.fontSize)); // 确保至少1列
                
                // 安全初始化drops数组
                this.drops = Array.from({ length: this.columns }, () => 
                    Math.floor(Math.random() * -window.innerHeight)
                );

                // 性能自适应
                this.animationSpeed = Math.max(1, Math.floor(window.innerHeight / 500));
                
                // 梯度颜色
                this.gradient = this.ctx.createLinearGradient(0, 0, 0, window.innerHeight);
                this.gradient.addColorStop(0, '#0f0');
                this.gradient.addColorStop(0.2, '#0f0');
                this.gradient.addColorStop(1, 'rgba(0,255,0,0.1)');
            }

            drawMatrix() {
                if(!this.drops || this.drops.length === 0) return; // 安全保护
                
                this.ctx.fillStyle = 'rgba(0, 0, 0, 0.05)';
                this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
                
                this.ctx.fillStyle = this.gradient;
                this.ctx.font = `${this.fontSize}px monospace`;

                this.drops.forEach((drop, i) => {
                    const char = this.charSet[Math.floor(Math.random() * this.charSet.length)];
                    const x = i * this.fontSize;
                    const y = drop * this.fontSize;

                    this.ctx.fillText(char, x, y);

                    if (y > this.canvas.height && Math.random() > 0.975) {
                        this.drops[i] = 0;
                    }
                    this.drops[i] += this.animationSpeed;
                });
            }

            animate(timestamp) {
                // FPS计算
                const deltaTime = timestamp - this.lastFrameTime;
                this.fps = 1000 / (deltaTime || 16.67);
                this.lastFrameTime = timestamp;

                try {
                    this.drawMatrix();
                } catch (error) {
                    console.error('渲染错误:', error);
                    this.destroy();
                    return;
                }
                
                this.animationFrame = requestAnimationFrame(this.animate.bind(this));
            }

            destroy() {
                this.resizeObserver.disconnect();
                cancelAnimationFrame(this.animationFrame);
            }
        }

        // 安全初始化
        try {
            const matrix = new MatrixSystem();
            window.addEventListener('beforeunload', () => matrix.destroy());
        } catch (error) {
            console.error('系统初始化失败:', error);
            document.body.innerHTML = '<h1 style="color:#0f0">系统故障,请刷新页面</h1>';
        }
    </script>
</body>
</html>
        
预览
控制台