线性粒子

线性粒子汇聚特效

每个粒子都有独特的HSL颜色值,粒子颜色随时间渐变,形成彩虹流动效果,粒子间的连线呈现彩色,根据距离动态变化,鼠标移动会影响粒子运动(吸引和排斥),粒子在画布边界会反弹,底部版权信息,使用半透明背景增强可读性。

5800e691931ffbc25f53f6f428d4919.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;
            position: relative;
            font-family: 'Arial', sans-serif;
        }
        
        canvas {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%%;
            height: 100%%;
            z-index: 1;
        }
        
        .background-image {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%%;
            height: 100%%;
            background: url('https://images.unsplash.com/photo-1534447677768-be436bb09401?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%%3D%%3D&auto=format&fit=crop&w=1790&q=80') no-repeat center center;
            background-size: cover;
            opacity: 0.2;
            z-index: 0;
        }
        
        .footer {
            text-align: center;
            padding: 12px;
            position: fixed;
            bottom: 0;
            width: 100%%;
            z-index: 10;
            font-size: 0.9rem;
            color: rgba(255, 255, 255, 0.7);
            background: rgba(0, 0, 0, 0.3);
            backdrop-filter: blur(3px);
            letter-spacing: 1px;
            font-weight: 300;
        }
    </style>
</head>
<body>
    <div></div>
    <canvas id="particleCanvas"></canvas>
    
    <div>
        七彩粒子网络效果 | 使用Canvas实现 | 背景图来自Unsplash
    </div>

    <script>
        // 获取Canvas元素和上下文
        var canvas = document.getElementById("particleCanvas");
        var ctx = canvas.getContext("2d");
        
        // 调整Canvas大小
        function resize() {
            canvas.width = window.innerWidth;
            canvas.height = window.innerHeight;
        }
        
        resize();
        window.addEventListener("resize", resize);
        
        // 动画兼容处理
        var RAF = (function() {
            return window.requestAnimationFrame || 
                   window.webkitRequestAnimationFrame || 
                   window.mozRequestAnimationFrame || 
                   window.oRequestAnimationFrame || 
                   window.msRequestAnimationFrame || 
                   function(callback) {
                       window.setTimeout(callback, 1000 / 60);
                   };
        })();
        
        // 鼠标交互区域
        var warea = {x: null, y: null, max: 20000};
        
        // 鼠标移动事件
        window.onmousemove = function(e) {
            warea.x = e.clientX;
            warea.y = e.clientY;
        };
        
        // 鼠标离开事件
        window.onmouseout = function() {
            warea.x = null;
            warea.y = null;
        };
        
        // 粒子数组
        var dots = [];
        var particleCount = 300;
        var speedFactor = 1;
        
        // 初始化粒子
        function initParticles(count) {
            for (var i = 0; i < count; i++) {
                var x = Math.random() * canvas.width;
                var y = Math.random() * canvas.height;
                var xa = Math.random() * 2 - 1;
                var ya = Math.random() * 2 - 1;
                
                dots.push({
                    x: x,
                    y: y,
                    xa: xa,
                    ya: ya,
                    max: 6000,
                    color: Math.floor(Math.random() * 360) // 初始随机色相
                });
            }
        }
        
        // 初始化粒子
        initParticles(particleCount);
        
        // 粒子动画
        function animate() {
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            
            // 创建包含鼠标位置的新数组
            var ndots = [warea].concat(dots);
            
            // 更新和绘制每个粒子
            dots.forEach(function(dot) {
                // 更新粒子位置
                dot.x += dot.xa * speedFactor;
                dot.y += dot.ya * speedFactor;
                
                // 边界反弹
                dot.xa *= (dot.x > canvas.width || dot.x < 0) ? -1 : 1;
                dot.ya *= (dot.y > canvas.height || dot.y < 0) ? -1 : 1;
                
                // 更新粒子颜色 (随时间变化)
                dot.color = (dot.color + 0.1) %% 360;
                
                // 绘制粒子
                ctx.beginPath();
                ctx.arc(dot.x, dot.y, 1.5, 0, Math.PI * 2);
                ctx.fillStyle = `hsl(${dot.color}, 100%%, 65%%)`;
                ctx.fill();
                
                // 检查与其他粒子的距离
                for (var i = 0; i < ndots.length; i++) {
                    var d2 = ndots[i];
                    
                    if (dot === d2 || d2.x === null || d2.y === null) continue;
                    
                    var xc = dot.x - d2.x;
                    var yc = dot.y - d2.y;
                    var dis = xc * xc + yc * yc;
                    
                    if (dis < d2.max) {
                        // 计算距离比例
                        var ratio = (d2.max - dis) / d2.max;
                        
                        // 鼠标互动
                        if (d2 === warea && dis > (d2.max / 2)) {
                            dot.x -= xc * 0.03 * speedFactor;
                            dot.y -= yc * 0.03 * speedFactor;
                        }
                        
                        // 绘制连线
                        ctx.beginPath();
                        ctx.lineWidth = ratio / 1.5;
                        
                        // 根据距离设置连线颜色
                        var lineHue = (dot.color + (ratio * 60)) %% 360;
                        ctx.strokeStyle = `hsla(${lineHue}, 90%%, 70%%, ${ratio * 0.6})`;
                        
                        ctx.moveTo(dot.x, dot.y);
                        ctx.lineTo(d2.x, d2.y);
                        ctx.stroke();
                    }
                }
                
                // 移除已处理的粒子
                ndots.splice(ndots.indexOf(dot), 1);
            });
            
            RAF(animate);
        }
        
        // 启动动画
        setTimeout(animate, 100);
    </script>
</body>
</html>


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

留言