如何修改particle.js实现点击创建粒子及链接颜色脉冲效果
改造particle.js实现点击脉冲粒子效果
先搞懂particle.js的核心结构(不用啃全量代码)
particle.js的核心是pJS实例,初始化后就能拿到这个对象,重点关注这几个关键部分:
pJS.particles.array:存储所有粒子的数组,每个元素是Particle对象,包含x/y坐标、color颜色、size大小等属性pJS.links.array:存储粒子间连线的数组,每个元素是Link对象,记录连接的两个粒子(particleA和particleB)- 动画循环:靠
requestAnimationFrame驱动,每帧先执行pJS.fn.particles.update()更新粒子状态,再执行pJS.fn.canvas.draw()重绘画面
具体修改步骤&代码
1. 初始化particle.js并扩展脉冲属性
先按需求完成基础初始化,再给粒子和链接添加脉冲相关的状态属性:
// 初始化particle.js,基础配置可按需调整 const pJS = particlesJS('particles-js', { particles: { number: { value: 10 }, color: { value: '#ffffff' }, size: { value: 5 }, line_linked: { enable: true, distance: 150, color: '#ffffff', opacity: 0.4, width: 1 } }, interactivity: { events: { onhover: { enable: false } } // 先关闭hover避免干扰脉冲逻辑 }, retina_detect: true }); // 给现有粒子添加脉冲状态 pJS.particles.array.forEach(particle => { particle.isPulsing = false; particle.pulseProgress = 0; particle.pulseColor = '#ff0000'; }); // 给现有连线添加脉冲状态 pJS.links.array.forEach(link => { link.hasPulse = false; link.pulseProgress = 0; link.pulseColor = '#ff0000'; });
2. 添加点击创建粒子逻辑
监听页面点击事件,在点击位置生成新粒子,并触发初始脉冲:
document.addEventListener('click', (e) => { // 转换点击坐标为canvas内的相对坐标 const rect = pJS.canvas.el.getBoundingClientRect(); const x = e.clientX - rect.left; const y = e.clientY - rect.top; // 用particle.js自带的构造函数创建新粒子 const newParticle = new pJS.fn.particles.Particle(); newParticle.x = x; newParticle.y = y; newParticle.color = { value: '#ffffff' }; newParticle.isPulsing = true; // 标记为正在脉冲 newParticle.pulseProgress = 0; newParticle.pulseColor = '#ff0000'; // 将新粒子加入粒子数组 pJS.particles.array.push(newParticle); // 触发初始脉冲传递 triggerPulse(newParticle); });
3. 实现脉冲传递&状态更新逻辑
写函数处理脉冲触发和传递,并重写原动画更新函数加入脉冲进度控制:
// 触发粒子脉冲,传递给所有相连的粒子 function triggerPulse(particle) { // 筛选当前粒子的所有连接 const connectedLinks = pJS.links.array.filter(link => link.particleA === particle || link.particleB === particle ); connectedLinks.forEach(link => { // 标记链接处于脉冲状态 link.hasPulse = true; link.pulseProgress = 0; link.pulseColor = particle.pulseColor; // 找到链接的另一端粒子 const targetParticle = link.particleA === particle ? link.particleB : link.particleA; // 延迟模拟脉冲传递时间,之后触发目标粒子的脉冲 setTimeout(() => { if (!targetParticle.isPulsing) { targetParticle.isPulsing = true; targetParticle.pulseProgress = 0; targetParticle.pulseColor = particle.pulseColor; // 递归触发目标粒子的脉冲传递 triggerPulse(targetParticle); } }, 500); // 传递延迟可按需调整 }); } // 重写粒子更新函数,加入脉冲进度更新 const originalUpdateParticles = pJS.fn.particles.update; pJS.fn.particles.update = function() { originalUpdateParticles.call(this); // 先执行原有的粒子更新逻辑 // 更新每个粒子的脉冲进度 this.particles.array.forEach(particle => { if (particle.isPulsing) { particle.pulseProgress += 0.02; // 进度到1时结束脉冲 if (particle.pulseProgress >= 1) { particle.isPulsing = false; particle.pulseProgress = 0; } } }); // 更新每个链接的脉冲进度 this.links.array.forEach(link => { if (link.hasPulse) { link.pulseProgress += 0.02; if (link.pulseProgress >= 1) { link.hasPulse = false; link.pulseProgress = 0; } } }); };
4. 修改渲染函数,绘制脉冲视觉效果
重写原有的粒子和连线绘制函数,根据脉冲状态动态调整颜色:
// 重写粒子绘制函数 const originalDrawParticle = pJS.fn.canvas.drawParticle; pJS.fn.canvas.drawParticle = function(particle) { // 脉冲时混合原颜色和脉冲颜色,按进度过渡 if (particle.isPulsing) { const originalColor = particle.color.value; const pulseColor = particle.pulseColor; const mixedColor = mixColors(originalColor, pulseColor, particle.pulseProgress); particle.color.value = mixedColor; } originalDrawParticle.call(this, particle); // 绘制完成后恢复原颜色,避免影响下一帧 if (particle.isPulsing) { particle.color.value = '#ffffff'; // 替换为你的粒子默认颜色 } }; // 重写连线绘制函数 const originalDrawLink = pJS.fn.canvas.drawLink; pJS.fn.canvas.drawLink = function(link) { if (link.hasPulse) { const originalColor = link.color; const pulseColor = link.pulseColor; const mixedColor = mixColors(originalColor, pulseColor, link.pulseProgress); link.color = mixedColor; } originalDrawLink.call(this, link); // 绘制完成后恢复原颜色 if (link.hasPulse) { link.color = '#ffffff'; // 替换为你的连线默认颜色 } }; // 辅助函数:混合两种RGB颜色 function mixColors(color1, color2, progress) { const rgb1 = hexToRgb(color1); const rgb2 = hexToRgb(color2); // 按进度插值计算混合后的RGB值 const r = Math.floor(rgb1.r + (rgb2.r - rgb1.r) * progress); const g = Math.floor(rgb1.g + (rgb2.g - rgb1.g) * progress); const b = Math.floor(rgb1.b + (rgb2.b - rgb1.b) * progress); return `rgb(${r}, ${g}, ${b})`; } // 辅助函数:十六进制颜色转RGB function hexToRgb(hex) { const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); return result ? { r: parseInt(result[1], 16), g: parseInt(result[2], 16), b: parseInt(result[3], 16) } : { r: 255, g: 255, b: 255 }; }
代码逻辑讲解
- 初始化扩展:在基础配置后给粒子和链接添加脉冲状态属性,用来跟踪脉冲的启动、进度和颜色。
- 点击创建粒子:利用particle.js自带的
Particle构造函数生成新粒子,加入数组后直接触发脉冲传递。 - 脉冲传递:
triggerPulse函数负责找到当前粒子的所有连接,标记链接的脉冲状态,延迟后触发目标粒子的脉冲,形成递归传递;重写的更新函数负责每帧推进脉冲进度,控制脉冲的开始和结束。 - 渲染调整:通过重写原绘制函数,在绘制前根据脉冲进度混合颜色,绘制后恢复原颜色,既实现脉冲视觉效果,又不影响粒子的正常状态。两个辅助函数负责颜色格式转换和混合,保证过渡自然。
自定义调整提示
- 脉冲速度:修改
pulseProgress += 0.02的步长,数值越大脉冲越快 - 传递延迟:调整
setTimeout的毫秒数,数值越大脉冲传递越慢 - 脉冲颜色:直接修改
pulseColor的十六进制值即可
内容的提问来源于stack exchange,提问作者Rahul Jaiswal
相关产品推荐
相关产品推荐

