1 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
2 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
3 | return new (P || (P = Promise))(function (resolve, reject) {
|
4 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
5 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
6 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
7 | step((generator = generator.apply(thisArg, _arguments || [])).next());
|
8 | });
|
9 | };
|
10 | import { Canvas } from "./Canvas";
|
11 | import { Particles } from "./Particles";
|
12 | import { Retina } from "./Retina";
|
13 | import { FrameManager } from "./FrameManager";
|
14 | import { Options } from "../Options/Classes/Options";
|
15 | import { EventListeners, Plugins, Utils } from "../Utils";
|
16 | import { Vector } from "./Particle/Vector";
|
17 | export class Container {
|
18 | constructor(id, sourceOptions, ...presets) {
|
19 | this.id = id;
|
20 | this.fpsLimit = 60;
|
21 | this.firstStart = true;
|
22 | this.started = false;
|
23 | this.destroyed = false;
|
24 | this.paused = true;
|
25 | this.lastFrameTime = 0;
|
26 | this.pageHidden = false;
|
27 | this._sourceOptions = sourceOptions;
|
28 | this.retina = new Retina(this);
|
29 | this.canvas = new Canvas(this);
|
30 | this.particles = new Particles(this);
|
31 | this.drawer = new FrameManager(this);
|
32 | this.pathGenerator = {
|
33 | generate: () => {
|
34 | const v = Vector.create(0, 0);
|
35 | v.length = Math.random();
|
36 | v.angle = Math.random() * Math.PI * 2;
|
37 | return v;
|
38 | },
|
39 | init: () => {
|
40 | },
|
41 | update: () => {
|
42 | },
|
43 | };
|
44 | this.interactivity = {
|
45 | mouse: {
|
46 | clicking: false,
|
47 | inside: false,
|
48 | },
|
49 | };
|
50 | this.bubble = {};
|
51 | this.repulse = { particles: [] };
|
52 | this.attract = { particles: [] };
|
53 | this.plugins = new Map();
|
54 | this.drawers = new Map();
|
55 | this.density = 1;
|
56 | this._options = new Options();
|
57 | this.actualOptions = new Options();
|
58 | for (const preset of presets) {
|
59 | this._options.load(Plugins.getPreset(preset));
|
60 | }
|
61 | const shapes = Plugins.getSupportedShapes();
|
62 | for (const type of shapes) {
|
63 | const drawer = Plugins.getShapeDrawer(type);
|
64 | if (drawer) {
|
65 | this.drawers.set(type, drawer);
|
66 | }
|
67 | }
|
68 | if (this._options) {
|
69 | this._options.load(this._sourceOptions);
|
70 | }
|
71 | this.eventListeners = new EventListeners(this);
|
72 | if (typeof IntersectionObserver !== "undefined" && IntersectionObserver) {
|
73 | this.intersectionObserver = new IntersectionObserver((entries) => this.intersectionManager(entries));
|
74 | }
|
75 | }
|
76 | get options() {
|
77 | return this._options;
|
78 | }
|
79 | get sourceOptions() {
|
80 | return this._sourceOptions;
|
81 | }
|
82 | play(force) {
|
83 | const needsUpdate = this.paused || force;
|
84 | if (this.firstStart && !this.actualOptions.autoPlay) {
|
85 | this.firstStart = false;
|
86 | return;
|
87 | }
|
88 | if (this.paused) {
|
89 | this.paused = false;
|
90 | }
|
91 | if (needsUpdate) {
|
92 | for (const [, plugin] of this.plugins) {
|
93 | if (plugin.play) {
|
94 | plugin.play();
|
95 | }
|
96 | }
|
97 | this.lastFrameTime = performance.now();
|
98 | }
|
99 | this.draw();
|
100 | }
|
101 | pause() {
|
102 | if (this.drawAnimationFrame !== undefined) {
|
103 | Utils.cancelAnimation(this.drawAnimationFrame);
|
104 | delete this.drawAnimationFrame;
|
105 | }
|
106 | if (this.paused) {
|
107 | return;
|
108 | }
|
109 | for (const [, plugin] of this.plugins) {
|
110 | if (plugin.pause) {
|
111 | plugin.pause();
|
112 | }
|
113 | }
|
114 | if (!this.pageHidden) {
|
115 | this.paused = true;
|
116 | }
|
117 | }
|
118 | draw() {
|
119 | this.drawAnimationFrame = Utils.animate((timestamp) => this.drawer.nextFrame(timestamp));
|
120 | }
|
121 | getAnimationStatus() {
|
122 | return !this.paused;
|
123 | }
|
124 | setNoise(noiseOrGenerator, init, update) {
|
125 | this.setPath(noiseOrGenerator, init, update);
|
126 | }
|
127 | setPath(pathOrGenerator, init, update) {
|
128 | if (!pathOrGenerator) {
|
129 | return;
|
130 | }
|
131 | if (typeof pathOrGenerator === "function") {
|
132 | this.pathGenerator.generate = pathOrGenerator;
|
133 | if (init) {
|
134 | this.pathGenerator.init = init;
|
135 | }
|
136 | if (update) {
|
137 | this.pathGenerator.update = update;
|
138 | }
|
139 | }
|
140 | else {
|
141 | if (pathOrGenerator.generate) {
|
142 | this.pathGenerator.generate = pathOrGenerator.generate;
|
143 | }
|
144 | if (pathOrGenerator.init) {
|
145 | this.pathGenerator.init = pathOrGenerator.init;
|
146 | }
|
147 | if (pathOrGenerator.update) {
|
148 | this.pathGenerator.update = pathOrGenerator.update;
|
149 | }
|
150 | }
|
151 | }
|
152 | destroy() {
|
153 | this.stop();
|
154 | this.canvas.destroy();
|
155 | for (const [, drawer] of this.drawers) {
|
156 | if (drawer.destroy) {
|
157 | drawer.destroy(this);
|
158 | }
|
159 | }
|
160 | for (const key of this.drawers.keys()) {
|
161 | this.drawers.delete(key);
|
162 | }
|
163 | this.destroyed = true;
|
164 | }
|
165 | exportImg(callback) {
|
166 | this.exportImage(callback);
|
167 | }
|
168 | exportImage(callback, type, quality) {
|
169 | var _a;
|
170 | return (_a = this.canvas.element) === null || _a === void 0 ? void 0 : _a.toBlob(callback, type !== null && type !== void 0 ? type : "image/png", quality);
|
171 | }
|
172 | exportConfiguration() {
|
173 | return JSON.stringify(this.actualOptions, undefined, 2);
|
174 | }
|
175 | refresh() {
|
176 | this.stop();
|
177 | return this.start();
|
178 | }
|
179 | reset() {
|
180 | this._options = new Options();
|
181 | return this.refresh();
|
182 | }
|
183 | stop() {
|
184 | if (!this.started) {
|
185 | return;
|
186 | }
|
187 | this.firstStart = true;
|
188 | this.started = false;
|
189 | this.eventListeners.removeListeners();
|
190 | this.pause();
|
191 | this.particles.clear();
|
192 | this.canvas.clear();
|
193 | if (this.interactivity.element instanceof HTMLElement && this.intersectionObserver) {
|
194 | this.intersectionObserver.observe(this.interactivity.element);
|
195 | }
|
196 | for (const [, plugin] of this.plugins) {
|
197 | if (plugin.stop) {
|
198 | plugin.stop();
|
199 | }
|
200 | }
|
201 | for (const key of this.plugins.keys()) {
|
202 | this.plugins.delete(key);
|
203 | }
|
204 | this.particles.linksColors = new Map();
|
205 | delete this.particles.grabLineColor;
|
206 | delete this.particles.linksColor;
|
207 | }
|
208 | loadTheme(name) {
|
209 | return __awaiter(this, void 0, void 0, function* () {
|
210 | this.actualOptions.setTheme(name);
|
211 | yield this.refresh();
|
212 | });
|
213 | }
|
214 | start() {
|
215 | return __awaiter(this, void 0, void 0, function* () {
|
216 | if (this.started) {
|
217 | return;
|
218 | }
|
219 | yield this.init();
|
220 | this.started = true;
|
221 | this.eventListeners.addListeners();
|
222 | if (this.interactivity.element instanceof HTMLElement && this.intersectionObserver) {
|
223 | this.intersectionObserver.observe(this.interactivity.element);
|
224 | }
|
225 | for (const [, plugin] of this.plugins) {
|
226 | if (plugin.startAsync !== undefined) {
|
227 | yield plugin.startAsync();
|
228 | }
|
229 | else if (plugin.start !== undefined) {
|
230 | plugin.start();
|
231 | }
|
232 | }
|
233 | this.play();
|
234 | });
|
235 | }
|
236 | init() {
|
237 | return __awaiter(this, void 0, void 0, function* () {
|
238 | this.actualOptions = new Options();
|
239 | this.actualOptions.load(this._options);
|
240 | this.retina.init();
|
241 | this.canvas.init();
|
242 | this.actualOptions.setResponsive(this.canvas.size.width, this.retina.pixelRatio, this._options);
|
243 | this.actualOptions.setTheme(undefined);
|
244 | this.fpsLimit = this.actualOptions.fpsLimit > 0 ? this.actualOptions.fpsLimit : 60;
|
245 | const availablePlugins = Plugins.getAvailablePlugins(this);
|
246 | for (const [id, plugin] of availablePlugins) {
|
247 | this.plugins.set(id, plugin);
|
248 | }
|
249 | for (const [, drawer] of this.drawers) {
|
250 | if (drawer.init) {
|
251 | yield drawer.init(this);
|
252 | }
|
253 | }
|
254 | for (const [, plugin] of this.plugins) {
|
255 | if (plugin.init) {
|
256 | plugin.init(this.actualOptions);
|
257 | }
|
258 | else if (plugin.initAsync !== undefined) {
|
259 | yield plugin.initAsync(this.actualOptions);
|
260 | }
|
261 | }
|
262 | this.canvas.resize();
|
263 | this.particles.init();
|
264 | this.particles.setDensity();
|
265 | });
|
266 | }
|
267 | intersectionManager(entries) {
|
268 | if (!this.actualOptions.pauseOnOutsideViewport) {
|
269 | return;
|
270 | }
|
271 | for (const entry of entries) {
|
272 | if (entry.target !== this.interactivity.element) {
|
273 | continue;
|
274 | }
|
275 | if (entry.isIntersecting) {
|
276 | this.play();
|
277 | }
|
278 | else {
|
279 | this.pause();
|
280 | }
|
281 | }
|
282 | }
|
283 | }
|