From 4b7c90bfd5d4299f828bc855d08fb1c4781cbdf2 Mon Sep 17 00:00:00 2001 From: Matteo Bruni <176620+matteobruni@users.noreply.github.com> Date: Sun, 19 Dec 2021 12:31:11 +0100 Subject: [PATCH] feat: changed particles.js compatibility with a new plugin --- bundles/pjs/src/IParticlesJS.ts | 33 +++++++++++ bundles/pjs/src/IParticlesJSOptions.ts | 21 +++---- bundles/pjs/src/fixOptions.ts | 44 ++++++++++----- bundles/pjs/src/index.ts | 77 +++++++------------------- bundles/pjs/src/particlesJSPlugin.ts | 23 ++++++++ 5 files changed, 114 insertions(+), 84 deletions(-) create mode 100644 bundles/pjs/src/IParticlesJS.ts create mode 100644 bundles/pjs/src/particlesJSPlugin.ts diff --git a/bundles/pjs/src/IParticlesJS.ts b/bundles/pjs/src/IParticlesJS.ts new file mode 100644 index 00000000000..5fb2a377d8e --- /dev/null +++ b/bundles/pjs/src/IParticlesJS.ts @@ -0,0 +1,33 @@ +import type { Container } from "tsparticles-engine"; +import { IParticlesJSOptions } from "./IParticlesJSOptions"; + +/** + * [[include:pjsMigration.md]] + * @category Particles.js + */ +export interface IParticlesJS { + /** + * Loads the provided options to create a [[Container]] object. + * @deprecated this method is obsolete, please use the new tsParticles.load + * @param tagId the particles container element id + * @param options the options object to initialize the [[Container]] + */ + (tagId: string, options: IParticlesJSOptions): Promise; + + /** + * Loads the provided json with a GET request. + * The content will be used to create a [[Container]] object. + * @deprecated this method is obsolete, please use the new tsParticles.loadJSON + * @param tagId the particles container element id + * @param pathConfigJson the json path to use in the GET request + * @param callback called after the [[Container]] is loaded and it will be passed as a parameter + */ + load(tagId: string, pathConfigJson: string, callback: (container?: Container) => void): void; + + /** + * Adds an additional click handler to all the loaded [[Container]] objects. + * @deprecated this method is obsolete, please use the new tsParticles.setOnClickHandler + * @param callback the function called after the click event is fired + */ + setOnClickHandler(callback: EventListenerOrEventListenerObject): void; +} diff --git a/bundles/pjs/src/IParticlesJSOptions.ts b/bundles/pjs/src/IParticlesJSOptions.ts index d232bf42c7c..679a2d8feb1 100644 --- a/bundles/pjs/src/IParticlesJSOptions.ts +++ b/bundles/pjs/src/IParticlesJSOptions.ts @@ -1,7 +1,4 @@ -import type { - IOptions, - InteractivityDetect -} from "tsparticles-engine"; +import type { IOptions, InteractivityDetect } from "tsparticles-engine"; import type { IStroke } from "tsparticles-engine/Options/Interfaces/Particles/IStroke"; import type { IShapeValues } from "tsparticles-engine/Options/Interfaces/Particles/Shape/IShapeValues"; import type { ILinks } from "tsparticles-engine/Options/Interfaces/Particles/Links/ILinks"; @@ -34,8 +31,8 @@ export type IParticlesJSOptions = IOptions & { remove: { particles_nb?: number; }; - } - }, + }; + }; particles: IParticles & { line_linked?: ILinks; move: { @@ -43,18 +40,18 @@ export type IParticlesJSOptions = IOptions & { attract: { rotateX?: number; rotateY?: number; - } + }; }; number: { density: { value_area?: number; - } + }; }; opacity: { random?: boolean; anim?: IOpacityAnimation & { opacity_min?: number; - } + }; }; shape: { stroke?: IStroke; @@ -65,7 +62,7 @@ export type IParticlesJSOptions = IOptions & { random?: boolean; anim?: ISizeAnimation & { size_min?: number; - } + }; }; - } -} + }; +}; diff --git a/bundles/pjs/src/fixOptions.ts b/bundles/pjs/src/fixOptions.ts index ca29163a642..2005a2b760a 100644 --- a/bundles/pjs/src/fixOptions.ts +++ b/bundles/pjs/src/fixOptions.ts @@ -1,8 +1,4 @@ -import type { - ISourceOptions, - SingleOrMultiple, - RecursivePartial -} from "tsparticles-engine"; +import type { ISourceOptions, SingleOrMultiple, RecursivePartial } from "tsparticles-engine"; import type { IStroke } from "tsparticles-engine/Options/Interfaces/Particles/IStroke"; import type { IShapeValues } from "tsparticles-engine/Options/Interfaces/Particles/Shape/IShapeValues"; import type { IOpacityAnimation } from "tsparticles-engine/Options/Interfaces/Particles/Opacity/IOpacityAnimation"; @@ -43,7 +39,7 @@ const fixOptions = (options: RecursivePartial): ISourceOpti if (moveOptions.out_mode !== undefined) { if (!moveOptions.outModes) { - moveOptions.outModes = { default: moveOptions.out_mode } + moveOptions.outModes = { default: moveOptions.out_mode }; } else { if (typeof moveOptions.outModes === "object") { moveOptions.outModes.default = moveOptions.out_mode; @@ -66,16 +62,25 @@ const fixOptions = (options: RecursivePartial): ISourceOpti } if (opacityOptions.anim) { - opacityOptions.animation = deepExtend(opacityOptions.animation, opacityOptions.anim) as IOpacityAnimation; + opacityOptions.animation = deepExtend( + opacityOptions.animation, + opacityOptions.anim + ) as IOpacityAnimation; if (opacityOptions.anim.enable && opacityOptions.anim.opacity_min !== undefined) { - opacityOptions.value = setRangeValue(opacityOptions.value ?? opacityOptions.anim.opacity_min, opacityOptions.anim.opacity_min); + opacityOptions.value = setRangeValue( + opacityOptions.value ?? opacityOptions.anim.opacity_min, + opacityOptions.anim.opacity_min + ); } } } if (particlesOptions?.shape?.stroke) { - particlesOptions.stroke = deepExtend(particlesOptions.stroke, particlesOptions.shape.stroke) as SingleOrMultiple; + particlesOptions.stroke = deepExtend( + particlesOptions.stroke, + particlesOptions.shape.stroke + ) as SingleOrMultiple; } if (particlesOptions?.shape?.polygon) { @@ -83,7 +88,10 @@ const fixOptions = (options: RecursivePartial): ISourceOpti particlesOptions.shape.options = {}; } - particlesOptions.shape.options.polygon = deepExtend(particlesOptions.shape.options.polygon, particlesOptions.shape.polygon) as SingleOrMultiple; + particlesOptions.shape.options.polygon = deepExtend( + particlesOptions.shape.options.polygon, + particlesOptions.shape.polygon + ) as SingleOrMultiple; } if (particlesOptions?.shape?.image) { @@ -91,8 +99,10 @@ const fixOptions = (options: RecursivePartial): ISourceOpti particlesOptions.shape.options = {}; } - - particlesOptions.shape.options.image = deepExtend(particlesOptions.shape.options.image, particlesOptions.shape.image) as SingleOrMultiple; + particlesOptions.shape.options.image = deepExtend( + particlesOptions.shape.options.image, + particlesOptions.shape.image + ) as SingleOrMultiple; } const sizeOptions = particlesOptions.size; @@ -106,7 +116,10 @@ const fixOptions = (options: RecursivePartial): ISourceOpti sizeOptions.animation = deepExtend(sizeOptions.animation, sizeOptions.anim) as ISizeAnimation; if (sizeOptions.anim.enable && sizeOptions.anim.size_min !== undefined) { - sizeOptions.value = setRangeValue(sizeOptions.value ?? sizeOptions.anim.size_min, sizeOptions.anim.size_min); + sizeOptions.value = setRangeValue( + sizeOptions.value ?? sizeOptions.anim.size_min, + sizeOptions.anim.size_min + ); } } } @@ -135,7 +148,10 @@ const fixOptions = (options: RecursivePartial): ISourceOpti if (modesOptions) { if (modesOptions.grab?.line_linked) { - modesOptions.grab.links = deepExtend(modesOptions.grab.links, modesOptions.grab.line_linked) as IGrabLinks; + modesOptions.grab.links = deepExtend( + modesOptions.grab.links, + modesOptions.grab.line_linked + ) as IGrabLinks; } if (modesOptions.push?.particles_nb !== undefined) { diff --git a/bundles/pjs/src/index.ts b/bundles/pjs/src/index.ts index 7901f98e176..799c54c35c2 100644 --- a/bundles/pjs/src/index.ts +++ b/bundles/pjs/src/index.ts @@ -2,60 +2,25 @@ * [[include:pjsMigration.md]] * @packageDocumentation */ -import type { - Container, - Main, - Particle, - RecursivePartial -} from "tsparticles-engine"; +import type { Container, Main, Particle, RecursivePartial } from "tsparticles-engine"; import type { IParticlesJSOptions } from "./IParticlesJSOptions"; -import { fixOptions } from "./fixOptions"; - -/** - * [[include:pjsMigration.md]] - * @category Particles.js - */ -export interface IParticlesJS { - /** - * Loads the provided options to create a [[Container]] object. - * @deprecated this method is obsolete, please use the new tsParticles.load - * @param tagId the particles container element id - * @param options the options object to initialize the [[Container]] - */ - (tagId: string, options: IParticlesJSOptions): Promise; - - /** - * Loads the provided json with a GET request. - * The content will be used to create a [[Container]] object. - * @deprecated this method is obsolete, please use the new tsParticles.loadJSON - * @param tagId the particles container element id - * @param pathConfigJson the json path to use in the GET request - * @param callback called after the [[Container]] is loaded and it will be passed as a parameter - */ - load(tagId: string, pathConfigJson: string, callback: (container?: Container) => void): void; - - /** - * Adds an additional click handler to all the loaded [[Container]] objects. - * @deprecated this method is obsolete, please use the new tsParticles.setOnClickHandler - * @param callback the function called after the click event is fired - */ - setOnClickHandler(callback: EventListenerOrEventListenerObject): void; -} - -function fetchError(statusCode: number): void { - console.error(`Error tsParticles - fetch status: ${statusCode}`); - console.error("Error tsParticles - File config not found"); -} +import type { IParticlesJS } from "./IParticlesJS"; +import { ParticlesJSPlugin } from "./particlesJSPlugin"; const initPjs = (main: Main): { particlesJS: IParticlesJS; pJSDom: Container[] } => { + main.addPlugin(new ParticlesJSPlugin()); + /** * Loads the provided options to create a [[Container]] object. * @deprecated this method is obsolete, please use the new tsParticles.load * @param tagId the particles container element id * @param options the options object to initialize the [[Container]] */ - const particlesJS = (tagId: string, options: RecursivePartial): Promise => { - return main.load(tagId, fixOptions(options)); + const particlesJS = ( + tagId: string, + options: RecursivePartial + ): Promise => { + return main.load(tagId, options); }; /** @@ -67,19 +32,15 @@ const initPjs = (main: Main): { particlesJS: IParticlesJS; pJSDom: Container[] } * @param callback called after the [[Container]] is loaded and it will be passed as a parameter */ particlesJS.load = (tagId: string, pathConfigJson: string, callback: (container?: Container) => void): void => { - (async () => { - const response = await fetch(pathConfigJson); - - if (!response.ok) { - fetchError(response.status); - - return; - } - - const data = await response.json(); - - callback(await particlesJS(tagId, data)); - })(); + main.loadJSON(tagId, pathConfigJson) + .then((container) => { + if (container) { + callback(container); + } + }) + .catch(() => { + callback(undefined); + }); }; /** diff --git a/bundles/pjs/src/particlesJSPlugin.ts b/bundles/pjs/src/particlesJSPlugin.ts new file mode 100644 index 00000000000..5cd0266fa3f --- /dev/null +++ b/bundles/pjs/src/particlesJSPlugin.ts @@ -0,0 +1,23 @@ +import type { IPlugin, IContainerPlugin } from "tsparticles-engine"; +import type { Options } from "tsparticles-engine/Options/Classes/Options"; +import { fixOptions } from "./fixOptions"; + +export class ParticlesJSPlugin implements IPlugin { + readonly id: string; + + constructor() { + this.id = "particles-js-plugin"; + } + + needsPlugin(): boolean { + return true; + } + + getPlugin(): IContainerPlugin { + return {}; + } + + loadOptions(options: Options): void { + fixOptions(options); + } +}