A Svelte 5 component that converts any image into an interactive particle animation with mouse interaction, auto-shuffling, and customizable scaling.
ParticleImage.svelte to your project's component directorynpm install svelte-particle-image
<script>
import ParticleImage from './ParticleImage.svelte';
</script>
<ParticleImage imageSrc="/path/to/image.png" />
| Prop | Type | Default | Description |
|---|---|---|---|
imageSrc |
string |
- | Path or URL to the image |
| Prop | Type | Default | Description |
|---|---|---|---|
width |
string |
'100%' |
Container width (CSS value: px, %, vw) |
height |
string |
'192px' |
Container height (CSS value: px, vh, %) |
backgroundColor |
string |
'transparent' |
Background color behind particles (hex, rgb, rgba) |
| Prop | Type | Default | Description |
|---|---|---|---|
particleSize |
number |
1 |
Size of each particle in pixels (1-10 recommended) |
particleGap |
number |
0 |
Gap between sampled pixels (0 = dense, 5 = very sparse) |
monochrome |
boolean |
false |
Use single color instead of image colors |
monochromeColor |
string |
'#00ff96' |
Color when monochrome is enabled (hex format) |
| Prop | Type | Default | Description |
|---|---|---|---|
restless |
boolean |
true |
Particles have subtle random movement |
mouseForce |
number |
10000 |
Mouse repulsion strength (0 = disabled, 50000 = very strong) |
| Prop | Type | Default | Description |
|---|---|---|---|
autoShuffle |
boolean |
false |
Automatically scatter and reform particles |
shuffleInterval |
number |
5000 |
Time between shuffles in milliseconds |
| Prop | Type | Default | Description |
|---|---|---|---|
imageScale |
'cover' | 'contain' | 'fill' | 'none' |
'cover' |
How image scales to canvas |
imageFit |
'center' | 'top' | 'bottom' | 'left' | 'right' |
'center' |
Image position within canvas |
cover: Scales image to fill entire canvas, cropping if needed (like CSS background-size: cover)contain: Scales image to fit within canvas without cropping (like CSS background-size: contain)fill: Stretches image to exactly fill canvas (may distort aspect ratio)none: Uses original image size without scaling<ParticleImage
imageSrc="/hero-image.jpg"
width="100%"
height="100vh"
imageScale="cover"
backgroundColor="#000000"
particleSize={2}
particleGap={1}
/>
<ParticleImage
imageSrc="/logo.png"
height="300px"
monochrome={true}
monochromeColor="#00ff96"
backgroundColor="#000000"
imageScale="contain"
imageFit="center"
/>
<ParticleImage
imageSrc="/photo.jpg"
width="600px"
height="400px"
monochrome={false}
particleGap={1}
particleSize={2}
imageScale="cover"
mouseForce={15000}
/>
<ParticleImage
imageSrc="/icon.png"
particleGap={3}
particleSize={4}
mouseForce={0}
restless={false}
imageScale="contain"
backgroundColor="#f0f0f0"
/>
<ParticleImage
imageSrc="/artwork.png"
autoShuffle={true}
shuffleInterval={3000}
backgroundColor="rgba(0,0,0,0.8)"
particleSize={2}
restless={true}
/>
<ParticleImage
imageSrc="/large-image.png"
particleGap={3}
particleSize={2}
mouseForce={5000}
imageScale="cover"
/>
<ParticleImage
imageSrc="/banner.jpg"
width="100%"
height="50vh"
imageScale="cover"
imageFit="center"
particleSize={2}
/>
mouseForce > 0)particleGap: Use 2-4 for large images to reduce particle countparticleSize: Use 2-3 on high-DPI screens for better visibilitymouseForce: Reduce to 5000-8000 for smoother performancerestless: Set to false if you have many particle instancesApproximate number of particles generated:
particles ā (imageWidth Ć imageHeight) / ((particleGap + 1)²)
Recommendations:
particleGap={3} ā ~130,000 pixels / 16 = ~8,125 particles āparticleGap={5} ā ~230,000 pixels / 36 = ~6,400 particles āRequires modern browsers with:
Supported Browsers:
Not supported:
# Clone the repository
git clone https://github.com/yourusername/svelte-particle-image.git
cd svelte-particle-image
# Install dependencies
npm install
# Run development server
npm run dev
# Open http://localhost:5173
npm run build
svelte-particle-image/
āāā src/
ā āāā lib/
ā ā āāā ParticleImage.svelte # Main component
ā āāā routes/
ā āāā +page.svelte # Interactive demo page
āāā static/
ā āāā demo-images/ # Sample images
āāā README.md
āāā LICENSE
āāā package.json
āāā svelte.config.js
āāā vite.config.ts
<div class="my-container">
<ParticleImage
imageSrc="/image.png"
width="100%"
height="100%"
/>
</div>
<style>
.my-container {
border-radius: 12px;
overflow: hidden;
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
}
</style>
<ParticleImage
imageSrc="/image.png"
width="100%"
height="50vh"
imageScale="cover"
/>
imageSrc path is correctstatic/ folder for SvelteKit projectsparticleGaprestless modemouseForce valuevh units instead: height="50vh" (50% of viewport height)particleSize from 1 to 2 or 3imageScale modesMIT License
Copyright (c) 2024
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Inspired by the ParticleSlider concept by Tamino Martinius
Built with ā¤ļø using Svelte 5
Contributions are welcome! Please feel free to submit a Pull Request.
git checkout -b feature/amazing-feature)git commit -m 'Add some amazing feature')git push origin feature/amazing-feature)If you have any questions or issues: