鼠标粒子拖尾效果

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>鼠标粒子拖尾效果</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            overflow: hidden;
            background-color: #000;
            cursor: none;
        }
        canvas {
            display: block;
        }
        .link {
            position: fixed;
            bottom: 10px;
            right: 10px;
            color: white;
            font-family: Arial, sans-serif;
            text-decoration: none;
            z-index: 100;
        }
    </style>
</head>
<body>
    <canvas id="canvas"></canvas>
 

    <script>
        const canvas = document.getElementById('canvas');
        const ctx = canvas.getContext('2d');
        let particles = [];
        const particleCount = 50;
        const mouse = { x: null, y: null };
        
        // 设置画布大小为窗口大小
        function resizeCanvas() {
            canvas.width = window.innerWidth;
            canvas.height = window.innerHeight;
        }
        
        window.addEventListener('resize', resizeCanvas);
        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 = mouse.x || Math.random() * canvas.width;
                this.y = mouse.y || Math.random() * canvas.height;
                this.size = Math.random() * 5 + 1;
                this.speedX = Math.random() * 3 - 1.5;
                this.speedY = Math.random() * 3 - 1.5;
                this.color = `hsl(${Math.random() * 360}, 100%, 50%)`;
                this.opacity = Math.random() * 0.6 + 0.4;
            }
            
            update() {
                if (mouse.x && mouse.y) {
                    const dx = mouse.x - this.x;
                    const dy = mouse.y - this.y;
                    const distance = Math.sqrt(dx * dx + dy * dy);
                    
                    if (distance < 100) {
                        this.x += dx * 0.05;
                        this.y += dy * 0.05;
                    } else {
                        this.x += this.speedX;
                        this.y += this.speedY;
                    }
                } else {
                    this.x += this.speedX;
                    this.y += this.speedY;
                }
                
                // 边界检查
                if (this.x > canvas.width || this.x < 0) {
                    this.speedX = -this.speedX;
                }
                if (this.y > canvas.height || this.y < 0) {
                    this.speedY = -this.speedY;
                }
                
                // 随机改变大小和透明度
                this.size = Math.max(0.5, this.size - 0.01);
                this.opacity = Math.max(0.1, this.opacity - 0.002);
            }
            
            draw() {
                ctx.beginPath();
                ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
                ctx.fillStyle = this.color;
                ctx.globalAlpha = this.opacity;
                ctx.fill();
                ctx.globalAlpha = 1;
            }
        }
        
        // 初始化粒子
        function init() {
            particles = [];
            for (let i = 0; i < particleCount; i++) {
                particles.push(new Particle());
            }
        }
        
        // 动画循环
        function animate() {
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            
            // 更新和绘制粒子
            for (let i = 0; i < particles.length; i++) {
                particles[i].update();
                particles[i].draw();
                
                // 如果粒子太小或太透明,替换新的粒子
                if (particles[i].size <= 0.5 || particles[i].opacity <= 0.1) {
                    particles.splice(i, 1);
                    particles.push(new Particle());
                }
            }
            
            // 绘制粒子间的连线
            drawConnections();
            
            requestAnimationFrame(animate);
        }
        
        // 绘制粒子间的连线
        function drawConnections() {
            for (let i = 0; i < particles.length; i++) {
                for (let j = i + 1; j < particles.length; j++) {
                    const dx = particles[i].x - particles[j].x;
                    const dy = particles[i].y - particles[j].y;
                    const distance = Math.sqrt(dx * dx + dy * dy);
                    
                    if (distance < 100) {
                        ctx.beginPath();
                        ctx.strokeStyle = particles[i].color;
                        ctx.globalAlpha = 0.5 * (1 - distance / 100);
                        ctx.lineWidth = 0.5;
                        ctx.moveTo(particles[i].x, particles[i].y);
                        ctx.lineTo(particles[j].x, particles[j].y);
                        ctx.stroke();
                        ctx.globalAlpha = 1;
                    }
                }
            }
        }
        
        init();
        animate();
    </script>
</body>
</html>

<think>好的,用户想了解如何在HTML中实现鼠标粒子效果。首先,我需要回忆一下常见的实现方法。通常,这种效果会用到HTML5的Canvas元素,结合JavaScript来处理动画和交互。 首先,我应该确定基本的结构。需要创建一个Canvas元素,并设置其覆盖整个窗口,同时确保当窗口大小变化时Canvas能自适应调整。然后,监听鼠标的移动事件,获取鼠标的位置。 接下来是粒子效果的实现。粒子通常用对象或数组来管理,每个粒子有位置、速度、大小、颜色等属性。可能需要一个Particle类来封装这些属性和更新、绘制的方法。 然后,考虑动画循环。使用requestAnimationFrame来不断更新粒子的位置并重新绘制,形成动画效果。在更新粒子时,可以添加一些物理效果,比如速度逐渐减小,或者让粒子鼠标方向移动,产生跟随效果。 颜色变化方面,可以根据时间或粒子属性动态改变,比如使用HSL颜色模式,随着时间变化色相值,实现渐变效果。 还需要处理粒子的生命周期,比如当粒子远离鼠标一定距离后移除,或者透明度降低到一定程度后重新初始化,保持粒子数量稳定。 可能遇到的问题包括性能优化,比如避免过多的粒子导致卡顿,或者Canvas绘制效率。需要测试合适的粒子数量,并确保在每一帧中只进行必要的绘制操作。 最后,应该提供一个完整的代码示例,让用户可以复制并运行,看到实际效果。同时,解释代码的关键部分,帮助用户理解实现原理,并能自行调整参数或样式。</think>我们通过HTML5 Canvas和JavaScript实现鼠标粒子效果。以下是分步讲解和完整代码: 一、HTML结构 ```html <!DOCTYPE html> <html> <head> <style> canvas { position: fixed; top: 0; left: 0; z-index: -1; } body { margin: 0; overflow: hidden; } </style> </head> <body> <canvas id="canvas"></canvas> <script src="script.js"></script> </body> </html> ``` 二、JavaScript实现(script.js) ```javascript const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); // 设置画布尺寸 function resize() { canvas.width = window.innerWidth; canvas.height = window.innerHeight; } window.addEventListener('resize', resize); resize(); // 粒子配置 const particles = []; const particleCount = 100; const mouse = { x: null, y: null }; // 鼠标移动监听 canvas.addEventListener('mousemove', e => { mouse.x = e.clientX; mouse.y = e.clientY; }); // 粒子类 class Particle { constructor() { this.reset(); } reset() { this.x = mouse.x || canvas.width/2; this.y = mouse.y || canvas.height/2; this.size = Math.random() * 5 + 1; this.speedX = Math.random() * 3 - 1.5; this.speedY = Math.random() * 3 - 1.5; this.color = `hsl(${Math.random() * 360}, 100%, 50%)`; } update() { this.x += this.speedX; this.y += this.speedY; if (this.distance > 100 || this.size < 0.3) { this.reset(); } this.size -= 0.1; } get distance() { return Math.hypot(mouse.x - this.x, mouse.y - this.y); } draw() { ctx.fillStyle = this.color; ctx.beginPath(); ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2); ctx.fill(); } } // 初始化粒子 for (let i = 0; i < particleCount; i++) { particles.push(new Particle()); } // 动画循环 function animate() { ctx.fillStyle = 'rgba(0, 0, 0, 0.1)'; ctx.fillRect(0, 0, canvas.width, canvas.height); particles.forEach(particle => { particle.update(); particle.draw(); }); requestAnimationFrame(animate); } animate(); ``` 三、关键功能说明: 1. Canvas自适应:通过监听resize事件,确保画布始终充满窗口 2. 粒子系统: - 使用粒子对象存储位置、速度、颜色等属性 - 动态颜色使用HSL色彩空间实现彩虹效果 3. 鼠标跟随: - 实时获取鼠标坐标 - 粒子生成后逐渐扩散并缩小 4. 动画优化: - 使用requestAnimationFrame实现流畅动画 - 半透明背景填充产生效果 - 自动回收旧粒子生成新粒子 四、自定义调整建议: 1. 修改particleCount调整粒子数量 2. 调整Math.random()的系数改变运动速度 3. 修改hsl参数实现不同颜色效果 4. 改变ctx.fillStyle的透明度值调整长度 这个实现包含完整的物理模拟和颜色渐变效果粒子会跟随鼠标移动并产生彩虹效果。所有现代浏览器均可流畅运行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值