<html>
<head>
<title>平滑中心流星雨</title>
<style>
body { margin: 0; overflow: hidden; background: #000; }
canvas { display: block; }
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
class Meteor {
constructor() {
this.active = false;
this.delay = Math.random() * 3000; // 初始随机延迟(0-3秒)
this.trail = [];
}
reset() {
this.x = canvas.width/2;
this.y = canvas.height/2;
this.angle = Math.random() * Math.PI * 2;
this.speed = Math.random() * 3 + 1;
this.size = Math.random() * 1 + 0.5;
this.trailLength = 10 + Math.random() * 8;
this.maxDistance = Math.hypot(canvas.width, canvas.height) * 1.2;
this.active = true;
}
update() {
if (!this.active) {
this.delay -= 16;
if (this.delay <= 0) this.reset();
return;
}
// 轨迹管理
this.trail.push({ x: this.x, y: this.y });
if (this.trail.length > this.trailLength) this.trail.shift();
// 位置更新
this.x += Math.cos(this.angle) * this.speed;
this.y += Math.sin(this.angle) * this.speed;
// 渐显计算
const dx = this.x - canvas.width/2;
const dy = this.y - canvas.height/2;
this.alpha = Math.min(Math.hypot(dx, dy) / 80, 1);
// 边界重置
if (Math.abs(dx) > this.maxDistance || Math.abs(dy) > this.maxDistance) {
this.active = false;
this.delay = 100 + Math.random() * 500; // 重生间隔0.1-0.6秒
this.trail = [];
}
}
draw() {
if (!this.active) return;
// 绘制尾迹
this.trail.forEach((pos, i) => {
const ratio = i / this.trailLength;
ctx.beginPath();
ctx.arc(pos.x, pos.y,
this.size * (1 - ratio) * 0.6,
0, Math.PI*2);
ctx.fillStyle = `rgba(255,255,255,${(1 - ratio) * 0.3 * this.alpha})`;
ctx.fill();
});
// 绘制头部
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI*2);
ctx.fillStyle = `rgba(255,255,255,${this.alpha})`;
ctx.fill();
}
}
// 创建流星池(数量增加到150)
const meteors = Array(150).fill().map(() => new Meteor());
function animate() {
ctx.fillStyle = 'rgba(0, 0, 0, 0.05)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
meteors.forEach(meteor => {
meteor.update();
meteor.draw();
});
requestAnimationFrame(animate);
}
window.addEventListener('resize', () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
meteors.forEach(meteor => {
if (meteor.active) meteor.reset();
});
});
animate();
</script>
</body>
</html>
xxxxxxxxxx
xxxxxxxxxx