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;
}
感谢您的支持!
微信支付
请使用微信扫一扫完成支付
支付宝
请使用支付宝扫一扫完成支付