@tsparticles/interaction-particles-repulse
Version:
tsParticles repulse particles interaction
55 lines (54 loc) • 2.12 kB
JavaScript
import { ParticlesInteractorBase, Vector, clamp, getDistances, getRangeValue, } from "@tsparticles/engine";
import { ParticlesRepulse } from "./Options/Classes/ParticlesRepulse.js";
const minDistance = 0, identity = 1, squareExp = 2, minVelocity = 0;
export class Repulser extends ParticlesInteractorBase {
constructor(container) {
super(container);
}
clear() {
}
init() {
}
interact(p1) {
const container = this.container;
if (!p1.repulse) {
const repulseOpt1 = p1.options.repulse;
if (!repulseOpt1) {
return;
}
p1.repulse = {
distance: getRangeValue(repulseOpt1.distance) * container.retina.pixelRatio,
speed: getRangeValue(repulseOpt1.speed),
factor: getRangeValue(repulseOpt1.factor),
};
}
const pos1 = p1.getPosition(), query = container.particles.quadTree.queryCircle(pos1, p1.repulse.distance);
for (const p2 of query) {
if (p1 === p2 || p2.destroyed) {
continue;
}
const pos2 = p2.getPosition(), { dx, dy, distance } = getDistances(pos2, pos1), velocity = p1.repulse.speed * p1.repulse.factor;
if (distance > minDistance) {
const repulseFactor = clamp((identity - Math.pow(distance / p1.repulse.distance, squareExp)) * velocity, minVelocity, velocity), normVec = Vector.create((dx / distance) * repulseFactor, (dy / distance) * repulseFactor);
p2.position.addTo(normVec);
}
else {
const velocityVec = Vector.create(velocity, velocity);
p2.position.addTo(velocityVec);
}
}
}
isEnabled(particle) {
return particle.options.repulse?.enabled ?? false;
}
loadParticlesOptions(options, ...sources) {
if (!options.repulse) {
options.repulse = new ParticlesRepulse();
}
for (const source of sources) {
options.repulse.load(source?.repulse);
}
}
reset() {
}
}