网页中的七彩粒子特效
下面是七彩粒子的实现方法,粒子动画本质是通过 Canvas 逐帧绘制大量独立的「粒子对象」,并通过更新粒子属性(位置、速度、颜色、大小等)实现动态效果。
1. Canvas 初始化设置 Canvas 尺寸适配窗口、获取 2D 上下文
2. 粒子类封装定义粒子属性(位置、速度、颜色、大小)和方法(更新、绘制)
3. 动画循环逐帧清空画布 → 更新粒子状态 → 绘制粒子
4. 交互逻辑监听鼠标 / 触摸事件,修改粒子运动规则
5. 边界 / 碰撞处理粒子超出画布反弹、粒子间距离判断
6. 扩展效果粒子连线、颜色渐变、生命周期(出生 / 消亡)

6cb98ec443b0d7620c94cb58d09641d.png
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>七彩粒子</title>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body {
            background: #0f2027;
            min-height: 100vh;
            overflow: hidden;
            font-family: 'Arial', sans-serif;
        }
        canvas {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%%;
            height: 100%%;
            z-index: 1;
        }
        .footer {
            position: fixed;
            bottom: 0;
            width: 100%%;
            padding: 12px;
            text-align: center;
            color: rgba(255,255,255,0.7);
            background: rgba(0,0,0,0.3);
            backdrop-filter: blur(3px);
            font-size: 0.9rem;
            z-index: 10;
        }
    </style>
</head>
<body>
    <canvas id="particleCanvas"></canvas>
    <div class="footer">七彩粒子网络效果 | Canvas 实现 | 支持鼠标交互</div>

    <script>
        // ========== 配置项(可自定义) ==========
        const CONFIG = {
            particleCount: 300,    // 粒子数量
            particleSize: 1.5,     // 粒子大小
            speedFactor: 1,        // 运动速度
            lineMaxDistance: 6000, // 粒子连线最大距离(平方值)
            mouseMaxDistance: 20000,// 鼠标交互最大距离(平方值)
            hueStep: 0.1,          // 颜色渐变步长
            lineOpacity: 0.6,      // 连线透明度
            lineWidthRatio: 1.5    // 连线宽度比例
        };

        // ========== Canvas 基础配置 ==========
        const canvas = document.getElementById('particleCanvas');
        const ctx = canvas.getContext('2d');
        let mouse = { x: null, y: null }; // 鼠标位置

        // 适配窗口大小
        function resizeCanvas() {
            canvas.width = window.innerWidth;
            canvas.height = window.innerHeight;
        }
        resizeCanvas();
        window.addEventListener('resize', resizeCanvas);

        // 监听鼠标事件
        window.addEventListener('mousemove', (e) => {
            mouse.x = e.clientX;
            mouse.y = e.clientY;
        });
        window.addEventListener('mouseout', () => {
            mouse.x = null;
            mouse.y = null;
        });

        // ========== 粒子类 ==========
        class Particle {
            constructor() {
                // 初始位置(随机)
                this.x = Math.random() * canvas.width;
                this.y = Math.random() * canvas.height;
                // 初始速度(-1 ~ 1 随机)
                this.vx = (Math.random() - 0.5) * 2;
                this.vy = (Math.random() - 0.5) * 2;
                // 初始色相(0 ~ 360)
                this.hue = Math.floor(Math.random() * 360);
            }

            // 更新粒子状态(位置、颜色、边界反弹)
            update() {
                // 移动粒子
                this.x += this.vx * CONFIG.speedFactor;
                this.y += this.vy * CONFIG.speedFactor;

                // 边界反弹
                if (this.x < 0 || this.x > canvas.width) this.vx *= -1;
                if (this.y < 0 || this.y > canvas.height) this.vy *= -1;

                // 颜色渐变
                this.hue = (this.hue + CONFIG.hueStep) %% 360;
            }

            // 绘制粒子(圆形)
            draw() {
                ctx.beginPath();
                ctx.arc(this.x, this.y, CONFIG.particleSize, 0, Math.PI * 2);
                ctx.fillStyle = `hsl(${this.hue}, 100%%, 65%%)`;
                ctx.fill();
            }
        }

        // ========== 粒子系统 ==========
        let particles = [];

        // 初始化粒子
        function initParticles() {
            particles = [];
            for (let i = 0; i < CONFIG.particleCount; i++) {
                particles.push(new Particle());
            }
        }

        // 绘制粒子间连线
        function drawLines(particle, target) {
            if (!target.x || !target.y) return;

            // 计算粒子与目标的距离(平方值,避免开方提升性能)
            const dx = particle.x - target.x;
            const dy = particle.y - target.y;
            const distanceSq = dx * dx + dy * dy;

            // 判断是否在连线范围内
            const maxDist = target === mouse ? CONFIG.mouseMaxDistance : CONFIG.lineMaxDistance;
            if (distanceSq > maxDist) return;

            // 距离比例(0 ~ 1)
            const ratio = (maxDist - distanceSq) / maxDist;

            // 鼠标交互:粒子向鼠标反方向移动
            if (target === mouse && distanceSq > maxDist / 2) {
                particle.x -= dx * 0.03 * CONFIG.speedFactor;
                particle.y -= dy * 0.03 * CONFIG.speedFactor;
            }

            // 绘制连线
            ctx.beginPath();
            ctx.lineWidth = ratio / CONFIG.lineWidthRatio;
            const lineHue = (particle.hue + ratio * 60) %% 360;
            ctx.strokeStyle = `hsla(${lineHue}, 90%%, 70%%, ${ratio * CONFIG.lineOpacity})`;
            ctx.moveTo(particle.x, particle.y);
            ctx.lineTo(target.x, target.y);
            ctx.stroke();
        }

        // 动画主循环
        function animate() {
            // 清空画布(半透明叠加,可选:增加拖影效果)
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            // 若要拖影效果,替换为:ctx.fillStyle = 'rgba(15,32,39,0.1)'; ctx.fillRect(0,0,canvas.width,canvas.height);

            // 遍历所有粒子,更新并绘制
            particles.forEach(particle => {
                particle.update();
                particle.draw();

                // 绘制粒子与鼠标的连线
                drawLines(particle, mouse);

                // 绘制粒子与其他粒子的连线
                particles.forEach(otherParticle => {
                    if (particle !== otherParticle) {
                        drawLines(particle, otherParticle);
                    }
                });
            });

            requestAnimationFrame(animate);
        }

        // 初始化并启动动画
        initParticles();
        animate();
    </script>
</body>
</html>


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

文章附件
  • 暂无附件
希望可以帮助到你
微信赞赏二维码

希望本文内容对您有帮助

支付宝赞赏二维码

支付宝赞赏

留言