tsparticles
Version:
Easily create highly customizable particle, confetti and fireworks animations and use them as animated backgrounds for your website. Ready to use components available also for React, Vue.js (2.x and 3.x), Angular, Svelte, jQuery, Preact, Riot.js, Inferno.
106 lines (105 loc) • 3.54 kB
JavaScript
import { circleBounce, circleBounceDataFromParticle, clamp, getDistance } from "../../../Utils";
import { ParticlesInteractorBase } from "../../../Core";
function bounce(p1, p2) {
circleBounce(circleBounceDataFromParticle(p1), circleBounceDataFromParticle(p2));
}
function destroy(p1, p2) {
if (!p1.unbreakable && !p2.unbreakable) {
bounce(p1, p2);
}
if (p1.getRadius() === undefined && p2.getRadius() !== undefined) {
p1.destroy();
}
else if (p1.getRadius() !== undefined && p2.getRadius() === undefined) {
p2.destroy();
}
else if (p1.getRadius() !== undefined && p2.getRadius() !== undefined) {
if (p1.getRadius() >= p2.getRadius()) {
p2.destroy();
}
else {
p1.destroy();
}
}
}
export class Collider extends ParticlesInteractorBase {
constructor(container) {
super(container);
}
isEnabled(particle) {
return particle.options.collisions.enable;
}
reset() {
}
async interact(p1) {
const container = this.container;
const pos1 = p1.getPosition();
const radius1 = p1.getRadius();
const query = container.particles.quadTree.queryCircle(pos1, radius1 * 2);
for (const p2 of query) {
if (p1 === p2 ||
!p2.options.collisions.enable ||
p1.options.collisions.mode !== p2.options.collisions.mode ||
p2.destroyed ||
p2.spawning) {
continue;
}
const pos2 = p2.getPosition();
if (Math.round(pos1.z) !== Math.round(pos2.z)) {
continue;
}
const dist = getDistance(pos1, pos2);
const radius2 = p2.getRadius();
const distP = radius1 + radius2;
if (dist <= distP) {
this.resolveCollision(p1, p2);
}
}
}
resolveCollision(p1, p2) {
switch (p1.options.collisions.mode) {
case "absorb": {
this.absorb(p1, p2);
break;
}
case "bounce": {
bounce(p1, p2);
break;
}
case "destroy": {
destroy(p1, p2);
break;
}
}
}
absorb(p1, p2) {
const container = this.container;
const fps = container.fpsLimit / 1000;
if (p1.getRadius() === undefined && p2.getRadius() !== undefined) {
p1.destroy();
}
else if (p1.getRadius() !== undefined && p2.getRadius() === undefined) {
p2.destroy();
}
else if (p1.getRadius() !== undefined && p2.getRadius() !== undefined) {
if (p1.getRadius() >= p2.getRadius()) {
const factor = clamp(p1.getRadius() / p2.getRadius(), 0, p2.getRadius()) * fps;
p1.size.value += factor;
p2.size.value -= factor;
if (p2.getRadius() <= container.retina.pixelRatio) {
p2.size.value = 0;
p2.destroy();
}
}
else {
const factor = clamp(p2.getRadius() / p1.getRadius(), 0, p1.getRadius()) * fps;
p1.size.value -= factor;
p2.size.value += factor;
if (p1.getRadius() <= container.retina.pixelRatio) {
p1.size.value = 0;
p1.destroy();
}
}
}
}
}