UNPKG

10.1 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.Particles = void 0;
4const Particle_1 = require("./Particle");
5const Utils_1 = require("../Utils");
6const InteractionManager_1 = require("./Particle/InteractionManager");
7const ParticlesOptions_1 = require("../Options/Classes/Particles/ParticlesOptions");
8class Particles {
9 constructor(container) {
10 this.container = container;
11 this.nextId = 0;
12 this.array = [];
13 this.limit = 0;
14 this.linksFreq = new Map();
15 this.trianglesFreq = new Map();
16 this.interactionManager = new InteractionManager_1.InteractionManager(container);
17 const canvasSize = this.container.canvas.size;
18 this.linksColors = new Map();
19 this.quadTree = new Utils_1.QuadTree(new Utils_1.Rectangle(-canvasSize.width / 4, -canvasSize.height / 4, (canvasSize.width * 3) / 2, (canvasSize.height * 3) / 2), 4);
20 }
21 get count() {
22 return this.array.length;
23 }
24 init() {
25 const container = this.container;
26 const options = container.actualOptions;
27 this.linksFreq = new Map();
28 this.trianglesFreq = new Map();
29 let handled = false;
30 for (const particle of options.manualParticles) {
31 const pos = particle.position
32 ? {
33 x: (particle.position.x * container.canvas.size.width) / 100,
34 y: (particle.position.y * container.canvas.size.height) / 100,
35 }
36 : undefined;
37 this.addParticle(pos, particle.options);
38 }
39 for (const [, plugin] of container.plugins) {
40 if (plugin.particlesInitialization !== undefined) {
41 handled = plugin.particlesInitialization();
42 }
43 if (handled) {
44 break;
45 }
46 }
47 if (!handled) {
48 for (let i = this.count; i < options.particles.number.value; i++) {
49 this.addParticle();
50 }
51 }
52 if (options.infection.enable) {
53 for (let i = 0; i < options.infection.infections; i++) {
54 const notInfected = this.array.filter((p) => p.infecter.infectionStage === undefined);
55 const infected = Utils_1.Utils.itemFromArray(notInfected);
56 infected.infecter.startInfection(0);
57 }
58 }
59 this.interactionManager.init();
60 container.pathGenerator.init();
61 }
62 redraw() {
63 this.clear();
64 this.init();
65 this.draw({ value: 0, factor: 0 });
66 }
67 removeAt(index, quantity, override) {
68 if (index >= 0 && index <= this.count) {
69 for (const particle of this.array.splice(index, quantity !== null && quantity !== void 0 ? quantity : 1)) {
70 particle.destroy(override);
71 }
72 }
73 }
74 remove(particle, override) {
75 this.removeAt(this.array.indexOf(particle), undefined, override);
76 }
77 update(delta) {
78 const container = this.container;
79 const particlesToDelete = [];
80 container.pathGenerator.update();
81 for (const [, plugin] of container.plugins) {
82 if (plugin.update !== undefined) {
83 plugin.update(delta);
84 }
85 }
86 for (const particle of this.array) {
87 const resizeFactor = this.container.canvas.resizeFactor;
88 if (resizeFactor) {
89 particle.position.x *= resizeFactor.width;
90 particle.position.y *= resizeFactor.height;
91 }
92 particle.move(delta);
93 if (particle.destroyed) {
94 particlesToDelete.push(particle);
95 continue;
96 }
97 this.quadTree.insert(new Utils_1.Point(particle.getPosition(), particle));
98 }
99 for (const particle of particlesToDelete) {
100 this.remove(particle);
101 }
102 this.interactionManager.externalInteract(delta);
103 for (const particle of this.container.particles.array) {
104 particle.update(delta);
105 if (!particle.destroyed && !particle.spawning) {
106 this.interactionManager.particlesInteract(particle, delta);
107 }
108 }
109 delete container.canvas.resizeFactor;
110 }
111 draw(delta) {
112 const container = this.container;
113 container.canvas.clear();
114 const canvasSize = this.container.canvas.size;
115 this.quadTree = new Utils_1.QuadTree(new Utils_1.Rectangle(-canvasSize.width / 4, -canvasSize.height / 4, (canvasSize.width * 3) / 2, (canvasSize.height * 3) / 2), 4);
116 this.update(delta);
117 for (const [, plugin] of container.plugins) {
118 container.canvas.drawPlugin(plugin, delta);
119 }
120 for (const p of this.array) {
121 p.draw(delta);
122 }
123 }
124 clear() {
125 this.array = [];
126 }
127 push(nb, mouse, overrideOptions) {
128 const container = this.container;
129 const options = container.actualOptions;
130 const limit = options.particles.number.limit * container.density;
131 this.pushing = true;
132 if (limit > 0) {
133 const countToRemove = this.count + nb - limit;
134 if (countToRemove > 0) {
135 this.removeQuantity(countToRemove);
136 }
137 }
138 for (let i = 0; i < nb; i++) {
139 this.addParticle(mouse === null || mouse === void 0 ? void 0 : mouse.position, overrideOptions);
140 }
141 this.pushing = false;
142 }
143 addParticle(position, overrideOptions) {
144 return this.pushParticle(position, overrideOptions);
145 }
146 addSplitParticle(parent) {
147 const splitOptions = parent.options.destroy.split;
148 const options = new ParticlesOptions_1.ParticlesOptions();
149 options.load(parent.options);
150 const factor = Utils_1.NumberUtils.getRangeValue(splitOptions.factor.value);
151 options.color.load({
152 value: {
153 hsl: parent.getFillColor(),
154 },
155 });
156 if (typeof options.size.value === "number") {
157 options.size.value /= factor;
158 }
159 else {
160 options.size.value.min /= factor;
161 options.size.value.max /= factor;
162 }
163 options.load(splitOptions.particles);
164 const offset = Utils_1.NumberUtils.setRangeValue(-parent.size.value, parent.size.value);
165 const position = {
166 x: parent.position.x + Utils_1.NumberUtils.randomInRange(offset),
167 y: parent.position.y + Utils_1.NumberUtils.randomInRange(offset),
168 };
169 return this.pushParticle(position, options, (particle) => {
170 if (particle.size.value < 0.5) {
171 return false;
172 }
173 particle.velocity.length = Utils_1.NumberUtils.randomInRange(Utils_1.NumberUtils.setRangeValue(parent.velocity.length, particle.velocity.length));
174 particle.splitCount = parent.splitCount + 1;
175 particle.unbreakable = true;
176 setTimeout(() => {
177 particle.unbreakable = false;
178 }, 500);
179 return true;
180 });
181 }
182 removeQuantity(quantity) {
183 this.removeAt(0, quantity);
184 }
185 getLinkFrequency(p1, p2) {
186 const key = `${Math.min(p1.id, p2.id)}_${Math.max(p1.id, p2.id)}`;
187 let res = this.linksFreq.get(key);
188 if (res === undefined) {
189 res = Math.random();
190 this.linksFreq.set(key, res);
191 }
192 return res;
193 }
194 getTriangleFrequency(p1, p2, p3) {
195 let [id1, id2, id3] = [p1.id, p2.id, p3.id];
196 if (id1 > id2) {
197 [id2, id1] = [id1, id2];
198 }
199 if (id2 > id3) {
200 [id3, id2] = [id2, id3];
201 }
202 if (id1 > id3) {
203 [id3, id1] = [id1, id3];
204 }
205 const key = `${id1}_${id2}_${id3}`;
206 let res = this.trianglesFreq.get(key);
207 if (res === undefined) {
208 res = Math.random();
209 this.trianglesFreq.set(key, res);
210 }
211 return res;
212 }
213 setDensity() {
214 const options = this.container.actualOptions;
215 this.applyDensity(options.particles);
216 }
217 applyDensity(options) {
218 var _a;
219 if (!((_a = options.number.density) === null || _a === void 0 ? void 0 : _a.enable)) {
220 return;
221 }
222 const numberOptions = options.number;
223 const densityFactor = this.initDensityFactor(numberOptions.density);
224 const optParticlesNumber = numberOptions.value;
225 const optParticlesLimit = numberOptions.limit > 0 ? numberOptions.limit : optParticlesNumber;
226 const particlesNumber = Math.min(optParticlesNumber, optParticlesLimit) * densityFactor;
227 const particlesCount = this.count;
228 this.limit = numberOptions.limit * densityFactor;
229 if (particlesCount < particlesNumber) {
230 this.push(Math.abs(particlesNumber - particlesCount), undefined, options);
231 }
232 else if (particlesCount > particlesNumber) {
233 this.removeQuantity(particlesCount - particlesNumber);
234 }
235 }
236 initDensityFactor(densityOptions) {
237 const container = this.container;
238 if (!container.canvas.element || !densityOptions.enable) {
239 return 1;
240 }
241 const canvas = container.canvas.element;
242 const pxRatio = container.retina.pixelRatio;
243 return (canvas.width * canvas.height) / (densityOptions.factor * pxRatio * pxRatio * densityOptions.area);
244 }
245 pushParticle(position, overrideOptions, initializer) {
246 try {
247 const particle = new Particle_1.Particle(this.nextId, this.container, position, overrideOptions);
248 let canAdd = true;
249 if (initializer) {
250 canAdd = initializer(particle);
251 }
252 if (!canAdd) {
253 return;
254 }
255 this.array.push(particle);
256 this.nextId++;
257 return particle;
258 }
259 catch (e) {
260 console.warn(`error adding particle: ${e}`);
261 return;
262 }
263 }
264}
265exports.Particles = Particles;