
Photo Particle Effect is a JavaScript script that transforms your images into an interactive particle cloud.
It extracts pixel data from a source image and generates a canvas-based particle system that scatters and reforms in response to the user’s mouse interaction.
See it in action:
How to use it:
1. Download ‘photo-particles.js’ and put it at the end of your HTML document.
<script src="photo-particles.js"></script>
2. Wrap your image in a DIV container with the CSS class of ‘photo-particles-image’.
<div class="photo-particles-image"> <img src="demo.png" alt="Demo Image"> </div>
3. Initialize the particle controller and pass the ‘imageSrc’ in the options object:
document.addEventListener('DOMContentLoaded', () => {
const photoController = new PhotoParticleController({
imageSrc: 'demo.png',
// more options here
});
});4. Available options:
containerSelector: A string for the CSS selector of the image’s parent element. The script uses this to find where to place the canvas. Default:'.photo-particles-image'.imageSrc: A string specifying the path to your image file. This is required for the script to load pixel data.touchInfluenceRadius: A number defining the radius (in pixels) of the mouse interaction zone. Larger values mean the mouse affects particles from further away. Default:120.touchMaxForce: A number that sets the maximum strength of the force pushing particles away from the mouse cursor during interaction. Default:80.particleSamplingStep: A number that controls particle density. A higher number increases the spacing between particles, resulting in fewer particles and better performance. Default:2.particleBaseRadius: A number that sets the base size for each particle. The actual size also varies slightly based on the brightness of the source pixel. Default:1.8.particleColor: A function that receives ther,g, andbvalues for a particle and returns a CSS color string. This allows for custom color logic. Default:(r, g, b) => \rgba(${r}, ${g}, ${b}, 0.95)“.showToggle: A boolean that determines if the built-in toggle controls are visible. Set tofalseto hide all associated toggle elements. Default:true.
const photoController = new PhotoParticleController({
containerSelector: '.photo-particles-image',
imageSrc: 'assets/images/me.jpg',
touchInfluenceRadius: 120,
touchMaxForce: 80,
particleSamplingStep: 2,
particleBaseRadius: 1.8,
particleColor: (r, g, b) => `rgba(${r}, ${g}, ${b}, 0.95)`,
showToggle: true,
});FAQs
Q: Why am I getting a CORS error?
A: The script uses a canvas to read the image’s pixel data. Due to browser security policies, this is only allowed if the image is served from the same origin as the webpage. If you load the image from a different domain or CDN without the proper CORS headers, the browser will block the request. The easiest fix is to host the image on your own server.
Q: How does the library handle different image formats and sizes?
A: The library works with any image format supported by the browser’s Canvas API, including JPEG, PNG, WebP, and SVG. Images are automatically resized to a 120×120 pixel sampling grid during processing, so original image dimensions don’t affect performance. The particle canvas scales to match the original image’s display size while maintaining aspect ratio.
Q: What performance impact should I expect with large images or many particles?
A: Performance depends primarily on particle count, which is controlled by the particleSamplingStep parameter. A sampling step of 2 typically generates 2000-3000 particles, while a step of 4 reduces this to 500-750 particles. The library is optimized for 60 FPS on modern browsers, but mobile devices may benefit from higher sampling step values.







