Skip to content

Instantly share code, notes, and snippets.

@qmzik
Last active July 13, 2021 18:24
Show Gist options
  • Save qmzik/baeb76709d23991dc2995893df683dbd to your computer and use it in GitHub Desktop.
Save qmzik/baeb76709d23991dc2995893df683dbd to your computer and use it in GitHub Desktop.
interface IParticle {
element: HTMLElement;
size: number;
horizontalSpeed: number;
speedUp: number;
spinVal: number;
spinSpeed: number;
top: number;
left: number;
direction: -1 | 1;
}
interface IOptions {
element?: HTMLElement;
limit?: number;
sizes?: number[];
}
const defaultOptions: Required<IOptions> = {
element: document.body,
limit: 35,
sizes: [15, 20, 25, 35, 45],
}
class ParticlesFountain {
constructor(imageLink: string, options: IOptions = defaultOptions) {
this.src = imageLink;
this.options = {...defaultOptions, ...options};
this.addHandlers();
this.loop();
}
private options: Required<IOptions>;
private src: string;
private autoAddParticle: boolean = false;
private particles: IParticle[] = [];
private mouseY: number = 0;
private mouseX: number = 0;
public loop() {
if (this.autoAddParticle && this.particles.length < this.options.limit) {
this.createParticle();
}
this.updateParticles();
requestAnimationFrame(this.loop.bind(this));
}
public addHandlers() {
const tap = 'mousedown';
const tapEnd = 'mouseup';
const move = 'mousemove';
document.addEventListener(move, (e: any) => {
this.mouseX = e.pageX ?? (e.touches ? e.touches[0]?.pageX : 0);
this.mouseY = e.pageY ?? (e.touches ? e.touches[0]?.pageY : 0);
}, { passive: false });
document.addEventListener(tap, (e: any) => {
this.mouseX = e.pageX ?? (e.touches ? e.touches[0]?.pageX : 0);
this.mouseY = e.pageY ?? (e.touches ? e.touches[0]?.pageY : 0);
this.autoAddParticle = true;
});
document.addEventListener(tapEnd, () => {
this.autoAddParticle = false;
});
document.addEventListener('mouseleave', () => {
this.autoAddParticle = false;
});
}
public createParticle() {
const size = this.options.sizes[Math.floor(Math.random() * this.options.sizes.length)];
const horizontalSpeed = Math.random() * 10;
const speedUp = Math.random() * 25;
const spinVal = Math.random() * 360;
const spinSpeed = ((Math.random() * 35)) * (Math.random() <= 0.5 ? -1 : 1);
const top = (this.mouseY - size / 2);
const left = (this.mouseX - size / 2);
const direction = Math.random() <= 0.5 ? -1 : 1;
const particle = document.createElement('img');
particle.src = this.src;
particle.style.width = '30px';
particle.style.top = `${top}px`;
particle.style.left = `${left}px`;
particle.style.transform = `rotate(${spinVal}deg)`;
particle.style.position = 'absolute';
particle.style.willChange = 'transform';
particle.style.pointerEvents = 'none';
this.options.element.appendChild(particle);
this.particles.push({
element: particle,
size,
horizontalSpeed,
speedUp,
spinVal,
spinSpeed,
top,
left,
direction,
});
}
public changeImage(imageLink: string) {
this.src = imageLink;
}
public updateParticles() {
const height = document.body.clientHeight;
this.particles.forEach((p) => {
p.left = p.left - (p.horizontalSpeed * p.direction);
p.top = p.top - p.speedUp;
p.speedUp = Math.min(p.size, p.speedUp - 1);
p.spinVal = p.spinVal + p.spinSpeed;
if (p.top >= height + p.size) {
this.particles = this.particles.filter((o) => o !== p);
p.element.remove();
}
p.element.style.top = `${p.top}px`;
p.element.style.left = `${p.left}px`;
p.element.style.transform = `rotate(${p.spinVal}deg)`;
});
}
}
export default ParticlesFountain;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment