<!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>
index.html