JavaScript 粒子效果

JavaScript 粒子效果是一种视觉上非常吸引人的前端技术,它可以创建出跟随鼠标移动的粒子轨迹,营造出动态和互动的视觉效果。这种效果利用了Canvas
API和requestAnimationFrame,为网页增添了生动的视觉体验。

实现原理

JavaScript 粒子效果的核心原理:

  • 使用Canvas API创建画布和绘制粒子
  • 监听鼠标移动事件,获取鼠标位置
  • 在鼠标位置生成粒子,设置粒子的大小、速度和颜色
  • 使用requestAnimationFrame实现动画循环
  • 在动画循环中更新粒子位置、大小和生命周期
  • 移除生命周期结束的粒子,保持性能

核心代码

// 粒子效果
function createParticleEffect() {
    const canvas = document.createElement('canvas');
    canvas.className = 'code-crazy-particle-canvas';
    canvas.width = 400;
    canvas.height = 200;
    canvas.style.border = '1px solid #e0e0e0';
    canvas.style.borderRadius = '8px';
    
    const ctx = canvas.getContext('2d');
    const particles = [];
    
    // 鼠标位置
    let mouseX = canvas.width / 2;
    let mouseY = canvas.height / 2;
    
    // 监听鼠标移动
    canvas.addEventListener('mousemove', (e) => {
        const rect = canvas.getBoundingClientRect();
        mouseX = e.clientX - rect.left;
        mouseY = e.clientY - rect.top;
    });
    
    // 创建粒子
    function createParticle() {
        particles.push({
            x: mouseX,
            y: mouseY,
            size: Math.random() * 3 + 1,
            speedX: (Math.random() - 0.5) * 2,
            speedY: (Math.random() - 0.5) * 2,
            color: `hsl(${Math.random() * 360}, 100%, 50%)`,
            life: 60
        });
    }
    
    // 动画循环
    function animate() {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        
        // 创建新粒子
        if (Math.random() > 0.5) {
            createParticle();
        }
        
        // 更新和绘制粒子
        particles.forEach((particle, index) => {
            particle.x += particle.speedX;
            particle.y += particle.speedY;
            particle.size *= 0.97;
            particle.life--;
            
            ctx.fillStyle = particle.color;
            ctx.beginPath();
            ctx.arc(particle.x, particle.y, particle.size, 0, Math.PI * 2);
            ctx.fill();
            
            // 移除死亡粒子
            if (particle.life <= 0) {
                particles.splice(index, 1);
            }
        });
        
        requestAnimationFrame(animate);
    }
    
    animate();
    return canvas;
}

代码分析

让我们分析一下这段代码的工作原理:

  • 画布创建:创建一个Canvas元素,设置宽度、高度和样式
  • 鼠标位置跟踪:监听鼠标移动事件,实时更新鼠标在画布上的位置
  • 粒子创建:在鼠标位置生成新粒子,设置随机的大小、速度、颜色和生命周期
  • 动画循环:使用requestAnimationFrame创建平滑的动画循环
    • 清空画布
    • 随机创建新粒子
    • 更新粒子的位置、大小和生命周期
    • 绘制粒子
    • 移除生命周期结束的粒子

效果演示

使用场景

JavaScript 粒子效果适用于以下场景:

  • 网站背景
  • 鼠标跟随效果
  • 交互按钮或链接的反馈效果
  • 节日或活动主题页面
  • 游戏或互动应用

扩展与优化

你可以通过以下方式扩展和优化JavaScript 粒子效果:

  • 调整粒子参数:修改粒子的大小、速度、颜色和生命周期
  • 添加粒子行为:实现粒子之间的碰撞检测或吸引力
  • 响应式设计:使画布大小随屏幕尺寸变化
  • 性能优化:限制粒子数量,使用对象池减少内存开销
  • 添加交互效果:根据鼠标速度或点击创建不同效果

浏览器兼容性

JavaScript 粒子效果在现代浏览器中都能正常工作,包括:

  • Chrome
  • Firefox
  • Safari
  • Edge
  • Opera

对于不支持Canvas的旧浏览器,需要提供降级方案。

性能考量

JavaScript 粒子效果的性能优化:

  • 粒子数量控制:限制最大粒子数量,避免过多粒子导致性能下降
  • 画布大小:根据需要设置合适的画布大小,避免不必要的绘制区域
  • 动画优化:使用requestAnimationFrame而不是setTimeout或setInterval
  • 内存管理:及时移除死亡粒子,避免内存泄漏
  • 绘制优化:使用fillRect清空画布比clearRect更高效

实际应用示例

以下是一个更完整的粒子效果应用示例,包含更多交互效果:

// 增强版粒子效果
function createEnhancedParticleEffect() {
    const canvas = document.createElement('canvas');
    canvas.className = 'code-crazy-enhanced-particle-canvas';
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    canvas.style.position = 'fixed';
    canvas.style.top = '0';
    canvas.style.left = '0';
    canvas.style.zIndex = '-1';
    
    document.body.appendChild(canvas);
    
    const ctx = canvas.getContext('2d');
    const particles = [];
    
    // 鼠标位置
    let mouseX = canvas.width / 2;
    let mouseY = canvas.height / 2;
    let mouseSpeed = 0;
    let lastMouseX = mouseX;
    let lastMouseY = mouseY;
    
    // 监听鼠标移动
    canvas.addEventListener('mousemove', (e) => {
        lastMouseX = mouseX;
        lastMouseY = mouseY;
        mouseX = e.clientX;
        mouseY = e.clientY;
        
        // 计算鼠标速度
        const dx = mouseX - lastMouseX;
        const dy = mouseY - lastMouseY;
        mouseSpeed = Math.sqrt(dx * dx + dy * dy);
    });
    
    // 创建粒子
    function createParticle() {
        particles.push({
            x: mouseX,
            y: mouseY,
            size: Math.random() * 5 + 1,
            speedX: (Math.random() - 0.5) * (mouseSpeed / 5 || 2),
            speedY: (Math.random() - 0.5) * (mouseSpeed / 5 || 2),
            color: `hsl(${Math.random() * 360}, 100%, ${Math.random() * 30 + 50}%)`,
            life: Math.random() * 30 + 30
        });
    }
    
    // 动画循环
    function animate() {
        // 半透明背景,创建拖尾效果
        ctx.fillStyle = 'rgba(255, 255, 255, 0.1)';
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        
        // 根据鼠标速度创建粒子
        const particleCount = Math.min(Math.floor(mouseSpeed / 10), 5);
        for (let i = 0; i < particleCount; i++) {
            createParticle();
        }
        
        // 更新和绘制粒子
        particles.forEach((particle, index) => {
            particle.x += particle.speedX;
            particle.y += particle.speedY;
            particle.size *= 0.95;
            particle.life--;
            
            // 绘制粒子
            ctx.fillStyle = particle.color;
            ctx.beginPath();
            ctx.arc(particle.x, particle.y, particle.size, 0, Math.PI * 2);
            ctx.fill();
            
            // 移除死亡粒子
            if (particle.life <= 0) {
                particles.splice(index, 1);
            }
        });
        
        requestAnimationFrame(animate);
    }
    
    // 响应窗口大小变化
    window.addEventListener('resize', () => {
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;
    });
    
    animate();
    return canvas;
}

投币打赏
0 0 投票数
文章评分
订阅评论
提醒
用户头像
0 评论
最旧
最新 最多投票
内联反馈
查看所有评论