tsparticles
Version:
Easily create highly customizable particle 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.
284 lines (283 loc) • 9.64 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import { Canvas } from "./Canvas";
import { Particles } from "./Particles";
import { Retina } from "./Retina";
import { FrameManager } from "./FrameManager";
import { Options } from "../Options/Classes/Options";
import { EventListeners, Plugins, Utils } from "../Utils";
import { Vector } from "./Particle/Vector";
export class Container {
constructor(id, sourceOptions, ...presets) {
this.id = id;
this.fpsLimit = 60;
this.firstStart = true;
this.started = false;
this.destroyed = false;
this.paused = true;
this.lastFrameTime = 0;
this.pageHidden = false;
this._sourceOptions = sourceOptions;
this.retina = new Retina(this);
this.canvas = new Canvas(this);
this.particles = new Particles(this);
this.drawer = new FrameManager(this);
this.pathGenerator = {
generate: () => {
const v = Vector.create(0, 0);
v.length = Math.random();
v.angle = Math.random() * Math.PI * 2;
return v;
},
init: () => {
},
update: () => {
},
};
this.interactivity = {
mouse: {
clicking: false,
inside: false,
},
};
this.bubble = {};
this.repulse = { particles: [] };
this.attract = { particles: [] };
this.plugins = new Map();
this.drawers = new Map();
this.density = 1;
this._options = new Options();
this.actualOptions = new Options();
for (const preset of presets) {
this._options.load(Plugins.getPreset(preset));
}
const shapes = Plugins.getSupportedShapes();
for (const type of shapes) {
const drawer = Plugins.getShapeDrawer(type);
if (drawer) {
this.drawers.set(type, drawer);
}
}
if (this._options) {
this._options.load(this._sourceOptions);
}
this.eventListeners = new EventListeners(this);
if (typeof IntersectionObserver !== "undefined" && IntersectionObserver) {
this.intersectionObserver = new IntersectionObserver((entries) => this.intersectionManager(entries));
}
}
get options() {
return this._options;
}
get sourceOptions() {
return this._sourceOptions;
}
play(force) {
const needsUpdate = this.paused || force;
if (this.firstStart && !this.actualOptions.autoPlay) {
this.firstStart = false;
return;
}
if (this.paused) {
this.paused = false;
}
if (needsUpdate) {
for (const [, plugin] of this.plugins) {
if (plugin.play) {
plugin.play();
}
}
this.lastFrameTime = performance.now();
}
this.draw();
}
pause() {
if (this.drawAnimationFrame !== undefined) {
Utils.cancelAnimation(this.drawAnimationFrame);
delete this.drawAnimationFrame;
}
if (this.paused) {
return;
}
for (const [, plugin] of this.plugins) {
if (plugin.pause) {
plugin.pause();
}
}
if (!this.pageHidden) {
this.paused = true;
}
}
draw() {
this.drawAnimationFrame = Utils.animate((timestamp) => this.drawer.nextFrame(timestamp));
}
getAnimationStatus() {
return !this.paused;
}
setNoise(noiseOrGenerator, init, update) {
this.setPath(noiseOrGenerator, init, update);
}
setPath(pathOrGenerator, init, update) {
if (!pathOrGenerator) {
return;
}
if (typeof pathOrGenerator === "function") {
this.pathGenerator.generate = pathOrGenerator;
if (init) {
this.pathGenerator.init = init;
}
if (update) {
this.pathGenerator.update = update;
}
}
else {
if (pathOrGenerator.generate) {
this.pathGenerator.generate = pathOrGenerator.generate;
}
if (pathOrGenerator.init) {
this.pathGenerator.init = pathOrGenerator.init;
}
if (pathOrGenerator.update) {
this.pathGenerator.update = pathOrGenerator.update;
}
}
}
destroy() {
this.stop();
this.canvas.destroy();
for (const [, drawer] of this.drawers) {
if (drawer.destroy) {
drawer.destroy(this);
}
}
for (const key of this.drawers.keys()) {
this.drawers.delete(key);
}
this.destroyed = true;
}
exportImg(callback) {
this.exportImage(callback);
}
exportImage(callback, type, quality) {
var _a;
return (_a = this.canvas.element) === null || _a === void 0 ? void 0 : _a.toBlob(callback, type !== null && type !== void 0 ? type : "image/png", quality);
}
exportConfiguration() {
return JSON.stringify(this.actualOptions, undefined, 2);
}
refresh() {
this.stop();
return this.start();
}
reset() {
this._options = new Options();
return this.refresh();
}
stop() {
if (!this.started) {
return;
}
this.firstStart = true;
this.started = false;
this.eventListeners.removeListeners();
this.pause();
this.particles.clear();
this.canvas.clear();
if (this.interactivity.element instanceof HTMLElement && this.intersectionObserver) {
this.intersectionObserver.observe(this.interactivity.element);
}
for (const [, plugin] of this.plugins) {
if (plugin.stop) {
plugin.stop();
}
}
for (const key of this.plugins.keys()) {
this.plugins.delete(key);
}
this.particles.linksColors = new Map();
delete this.particles.grabLineColor;
delete this.particles.linksColor;
}
loadTheme(name) {
return __awaiter(this, void 0, void 0, function* () {
this.actualOptions.setTheme(name);
yield this.refresh();
});
}
start() {
return __awaiter(this, void 0, void 0, function* () {
if (this.started) {
return;
}
yield this.init();
this.started = true;
this.eventListeners.addListeners();
if (this.interactivity.element instanceof HTMLElement && this.intersectionObserver) {
this.intersectionObserver.observe(this.interactivity.element);
}
for (const [, plugin] of this.plugins) {
if (plugin.startAsync !== undefined) {
yield plugin.startAsync();
}
else if (plugin.start !== undefined) {
plugin.start();
}
}
this.play();
});
}
init() {
return __awaiter(this, void 0, void 0, function* () {
this.actualOptions = new Options();
this.actualOptions.load(this._options);
this.retina.init();
this.canvas.init();
this.actualOptions.setResponsive(this.canvas.size.width, this.retina.pixelRatio, this._options);
this.actualOptions.setTheme(undefined);
this.fpsLimit = this.actualOptions.fpsLimit > 0 ? this.actualOptions.fpsLimit : 60;
const availablePlugins = Plugins.getAvailablePlugins(this);
for (const [id, plugin] of availablePlugins) {
this.plugins.set(id, plugin);
}
for (const [, drawer] of this.drawers) {
if (drawer.init) {
yield drawer.init(this);
}
}
for (const [, plugin] of this.plugins) {
if (plugin.init) {
plugin.init(this.actualOptions);
}
else if (plugin.initAsync !== undefined) {
yield plugin.initAsync(this.actualOptions);
}
}
this.canvas.resize();
this.particles.init();
this.particles.setDensity();
});
}
intersectionManager(entries) {
if (!this.actualOptions.pauseOnOutsideViewport) {
return;
}
for (const entry of entries) {
if (entry.target !== this.interactivity.element) {
continue;
}
if (entry.isIntersecting) {
this.play();
}
else {
this.pause();
}
}
}
}