UNPKG

9.64 kBJavaScriptView Raw
1var __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};
10import { Canvas } from "./Canvas";
11import { Particles } from "./Particles";
12import { Retina } from "./Retina";
13import { FrameManager } from "./FrameManager";
14import { Options } from "../Options/Classes/Options";
15import { EventListeners, Plugins, Utils } from "../Utils";
16import { Vector } from "./Particle/Vector";
17export 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}