闪烁的星星和随机划过的流星
使用HTML5 Canvas实现:1.星星效果:

随机生成不同大小和亮度的星星

星星会缓慢闪烁,模拟真实星空效果

星星带有微弱的颜色(白色、淡黄色、淡蓝色、淡红色)

流星效果:

流星随机从屏幕左侧或顶部边缘出现

流星缓慢划过屏幕,速度可调节

流星带有渐变的拖尾效果,增强视觉体验

设置功能:

右上角设置图标,点击展开/收起设置面板

可以调整星星数量、流星频率、流星速度和星星闪烁速度

所有参数实时生效响应式设计:当窗口大小改变时,Canvas会自动调整大小并重新生成星星

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>星辰与流星</title>
    <style>
        body {
            margin: 0;
            overflow: hidden;
            background-color: #000;
            font-family: 'Arial', sans-serif;
        }
        canvas {
            display: block;
        }
        /* 设置图标样式 */
        .settings-icon {
            position: absolute;
            top: 20px;
            right: 20px;
            color: white;
            font-size: 24px;
            cursor: pointer;
            z-index: 100;
            background: rgba(0, 0, 0, 0.5);
            border-radius: 50%%;
            width: 40px;
            height: 40px;
            display: flex;
            align-items: center;
            justify-content: center;
            transition: all 0.3s;
        }
        .settings-icon:hover {
            transform: rotate(45deg);
            background: rgba(0, 0, 0, 0.7);
        }
        /* 设置面板样式 */
        .settings-panel {
            position: absolute;
            top: 70px;
            right: 20px;
            background: rgba(0, 0, 0, 0.8);
            color: white;
            padding: 20px;
            border-radius: 10px;
            width: 250px;
            display: none;
            z-index: 100;
            box-shadow: 0 0 15px rgba(255, 255, 255, 0.2);
        }
        .settings-panel h3 {
            margin-top: 0;
            border-bottom: 1px solid rgba(255, 255, 255, 0.3);
            padding-bottom: 10px;
        }
        .setting-group {
            margin-bottom: 15px;
        }
        .setting-group label {
            display: block;
            margin-bottom: 5px;
            font-size: 14px;
        }
        .setting-group input[type="range"] {
            width: 100%%;
        }
        .setting-value {
            font-size: 12px;
            color: #aaa;
            float: right;
        }
    </style>
</head>
<body>
    <div>⚙️</div>
    <div>
        <h3>星空设置</h3>
        <div>
            <label>星星数量 <span id="starCountValue">500</span></label>
            <input type="range" id="starCount" min="100" max="1000" value="500" step="50">
        </div>
        <div>
            <label>流星频率 <span id="meteorFrequencyValue">0.01</span></label>
            <input type="range" id="meteorFrequency" min="0.001" max="0.05" value="0.01" step="0.001">
        </div>
        <div>
            <label>流星速度 <span id="meteorSpeedValue">5</span></label>
            <input type="range" id="meteorSpeed" min="2" max="15" value="5" step="1">
        </div>
        <div>
            <label>星星闪烁速度 <span id="twinkleSpeedValue">0.5</span></label>
            <input type="range" id="twinkleSpeed" min="0.1" max="2" value="0.5" step="0.1">
        </div>
    </div>
    <canvas id="starCanvas"></canvas>

    <script>
        // 获取Canvas元素和上下文
        const canvas = document.getElementById('starCanvas');
        const ctx = canvas.getContext('2d');
        const settingsIcon = document.querySelector('.settings-icon');
        const settingsPanel = document.querySelector('.settings-panel');
        
        // 设置Canvas大小为窗口大小
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;
        
        // 配置参数
        let config = {
            starCount: 500,
            meteorFrequency: 0.01,
            meteorSpeed: 5,
            twinkleSpeed: 0.5
        };

        // 星星数组
        let stars = [];
        // 流星数组
        let meteors = [];
        
        // 星星类
        class Star {
            constructor() {
                this.x = Math.random() * canvas.width;
                this.y = Math.random() * canvas.height;
                this.size = Math.random() * 2 + 0.1;
                // 给星星添加微弱的颜色
                this.color = this.getRandomStarColor();
                this.brightness = 0.2 + Math.random() * 0.8;
                this.speed = config.twinkleSpeed * 0.001;
                this.phase = Math.random() * Math.PI * 2;
            }
            
            // 获取随机的星星颜色(主要是白色,但带有微弱色调)
            getRandomStarColor() {
                const colors = [
                    {r: 255, g: 255, b: 255}, // 白色
                    {r: 255, g: 255, b: 220}, // 淡黄色
                    {r: 220, g: 220, b: 255}, // 淡蓝色
                    {r: 255, g: 220, b: 220}  // 淡红色
                ];
                return colors[Math.floor(Math.random() * colors.length)];
            }
            
            update() {
                this.speed = config.twinkleSpeed * 0.001;
                this.phase += this.speed;
                this.brightness = 0.7 + 0.3 * Math.sin(this.phase);
            }
            
            draw() {
                ctx.beginPath();
                ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
                ctx.fillStyle = `rgba(${this.color.r}, ${this.color.g}, ${this.color.b}, ${this.brightness})`;
                ctx.fill();
            }
        }
        
        // 流星类
        class Meteor {
            constructor() {
                this.reset();
            }
            
            reset() {
                // 流星从屏幕左侧或顶部边缘开始
                const fromLeft = Math.random() > 0.5;
                if (fromLeft) {
                    this.x = 0;
                    this.y = Math.random() * canvas.height * 0.3;
                } else {
                    this.x = Math.random() * canvas.width * 0.3;
                    this.y = 0;
                }
                
                // 流星角度(向右下方向)
                this.angle = Math.atan2(canvas.height, canvas.width) + (Math.random() - 0.5) * 0.4;
                
                this.speed = config.meteorSpeed;
                this.size = 1 + Math.random() * 2;
                this.length = 20 + Math.random() * 50;
                this.trail = [];
                this.active = true;
            }
            
            update() {
                this.speed = config.meteorSpeed;
                this.x += Math.cos(this.angle) * this.speed * 0.3; // 降低速度因子
                this.y += Math.sin(this.angle) * this.speed * 0.3; // 降低速度因子
                
                // 添加当前位置到轨迹
                this.trail.push({x: this.x, y: this.y});
                
                // 保持轨迹长度
                if (this.trail.length > this.length) {
                    this.trail.shift();
                }
                
                // 如果流星离开屏幕,重置它
                if (this.x > canvas.width || this.y > canvas.height) {
                    this.active = false;
                }
            }
            
            draw() {
                if (this.trail.length < 2) return;
                
                // 绘制流星轨迹(渐变效果)
                for (let i = 0; i < this.trail.length - 1; i++) {
                    const point = this.trail[i];
                    const nextPoint = this.trail[i + 1];
                    
                    const progress = i / this.trail.length;
                    const alpha = progress * 0.8;
                    const width = this.size * progress;
                    
                    ctx.beginPath();
                    ctx.moveTo(point.x, point.y);
                    ctx.lineTo(nextPoint.x, nextPoint.y);
                    ctx.strokeStyle = `rgba(255, 255, 255, ${alpha})`;
                    ctx.lineWidth = width;
                    ctx.stroke();
                }
                
                // 绘制流星头部
                ctx.beginPath();
                ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
                ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
                ctx.fill();
            }
        }
        
        // 初始化星星
        function initStars() {
            stars = [];
            for (let i = 0; i < config.starCount; i++) {
                stars.push(new Star());
            }
        }
        
        // 动画循环
        function animate() {
            // 清除画布
            ctx.fillStyle = 'rgba(0, 0, 0, 0.2)';
            ctx.fillRect(0, 0, canvas.width, canvas.height);
            
            // 更新和绘制星星
            stars.forEach(star => {
                star.update();
                star.draw();
            });
            
            // 随机添加流星
            if (Math.random() < config.meteorFrequency && meteors.length < 5) {
                meteors.push(new Meteor());
            }
            
            // 更新和绘制流星
            meteors.forEach((meteor, index) => {
                if (meteor.active) {
                    meteor.update();
                    meteor.draw();
                } else {
                    // 移除不活动的流星
                    meteors.splice(index, 1);
                }
            });
            
            requestAnimationFrame(animate);
        }
        
        // 窗口大小调整时重置Canvas
        window.addEventListener('resize', () => {
            canvas.width = window.innerWidth;
            canvas.height = window.innerHeight;
            initStars();
        });
        
        // 设置图标点击事件
        settingsIcon.addEventListener('click', () => {
            settingsPanel.style.display = settingsPanel.style.display === 'block' ? 'none' : 'block';
        });
        
        // 初始化设置滑块
        document.getElementById('starCount').addEventListener('input', function() {
            config.starCount = parseInt(this.value);
            document.getElementById('starCountValue').textContent = this.value;
            initStars();
        });
        
        document.getElementById('meteorFrequency').addEventListener('input', function() {
            config.meteorFrequency = parseFloat(this.value);
            document.getElementById('meteorFrequencyValue').textContent = this.value;
        });
        
        document.getElementById('meteorSpeed').addEventListener('input', function() {
            config.meteorSpeed = parseInt(this.value);
            document.getElementById('meteorSpeedValue').textContent = this.value;
        });
        
        document.getElementById('twinkleSpeed').addEventListener('input', function() {
            config.twinkleSpeed = parseFloat(this.value);
            document.getElementById('twinkleSpeedValue').textContent = this.value;
        });
        
        // 初始化并开始动画
        initStars();
        animate();
    </script>
</body>
</html>


本文最后更新时间 2025-09-18
文章链接地址:
https://xzlo.blog/index.php/archives/66/
本站文章除注明[转载|引用|原文]出处外,均为本站原生内容,转载前请注明出处

留言