@tsparticles/engine 4.0.0-alpha.8 → 4.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (307) hide show
  1. package/155.min.js +1 -0
  2. package/README.md +41 -28
  3. package/browser/Core/CanvasManager.js +303 -0
  4. package/browser/Core/Container.js +134 -101
  5. package/browser/Core/Engine.js +29 -162
  6. package/browser/Core/Particle.js +197 -183
  7. package/browser/Core/ParticlesManager.js +363 -0
  8. package/browser/Core/RenderManager.js +303 -0
  9. package/browser/Core/Retina.js +6 -6
  10. package/browser/Core/Utils/Constants.js +2 -2
  11. package/browser/Core/Utils/EventListeners.js +67 -63
  12. package/browser/Core/Utils/PluginManager.js +145 -0
  13. package/browser/Core/Utils/Ranges.js +29 -10
  14. package/browser/Core/Utils/SpatialHashGrid.js +102 -0
  15. package/browser/Core/Utils/Vectors.js +17 -18
  16. package/browser/Options/Classes/AnimatableColor.js +1 -0
  17. package/browser/Options/Classes/AnimationOptions.js +8 -0
  18. package/browser/Options/Classes/Background/Background.js +6 -0
  19. package/browser/Options/Classes/ColorAnimation.js +12 -1
  20. package/browser/Options/Classes/FullScreen/FullScreen.js +2 -0
  21. package/browser/Options/Classes/HslAnimation.js +4 -5
  22. package/browser/Options/Classes/Options.js +67 -8
  23. package/browser/Options/Classes/OptionsColor.js +1 -0
  24. package/browser/Options/Classes/Particles/Bounce/ParticlesBounce.js +2 -0
  25. package/browser/Options/Classes/Particles/Effect/Effect.js +3 -4
  26. package/browser/Options/Classes/Particles/Fill.js +28 -0
  27. package/browser/Options/Classes/Particles/Move/Move.js +17 -3
  28. package/browser/Options/Classes/Particles/Move/MoveAngle.js +2 -0
  29. package/browser/Options/Classes/Particles/Move/MoveCenter.js +4 -0
  30. package/browser/Options/Classes/Particles/Move/MoveGravity.js +4 -0
  31. package/browser/Options/Classes/Particles/Move/OutModes.js +5 -0
  32. package/browser/Options/Classes/Particles/Move/Path/MovePath.js +5 -0
  33. package/browser/Options/Classes/Particles/Move/Spin.js +3 -0
  34. package/browser/Options/Classes/Particles/Number/ParticlesDensity.js +3 -0
  35. package/browser/Options/Classes/Particles/Number/ParticlesNumber.js +3 -0
  36. package/browser/Options/Classes/Particles/Number/ParticlesNumberLimit.js +2 -0
  37. package/browser/Options/Classes/Particles/Opacity/Opacity.js +1 -0
  38. package/browser/Options/Classes/Particles/Opacity/OpacityAnimation.js +1 -0
  39. package/browser/Options/Classes/Particles/ParticlesOptions.js +29 -9
  40. package/browser/Options/Classes/Particles/Shape/Shape.js +3 -4
  41. package/browser/Options/Classes/Particles/Size/Size.js +1 -0
  42. package/browser/Options/Classes/Particles/Size/SizeAnimation.js +1 -0
  43. package/browser/Options/Classes/Particles/Stroke.js +3 -0
  44. package/browser/Options/Classes/Particles/ZIndex/ZIndex.js +3 -0
  45. package/browser/Options/Classes/ResizeEvent.js +2 -0
  46. package/browser/Options/Classes/ValueWithRandom.js +3 -4
  47. package/browser/Utils/CanvasUtils.js +44 -51
  48. package/browser/Utils/ColorUtils.js +51 -40
  49. package/browser/Utils/EventDispatcher.js +1 -0
  50. package/browser/Utils/LogUtils.js +1 -0
  51. package/browser/Utils/MathUtils.js +12 -7
  52. package/browser/Utils/OptionsUtils.js +2 -2
  53. package/browser/Utils/Utils.js +109 -31
  54. package/browser/exports.js +1 -2
  55. package/cjs/Core/CanvasManager.js +303 -0
  56. package/cjs/Core/Container.js +134 -101
  57. package/cjs/Core/Engine.js +29 -162
  58. package/cjs/Core/Particle.js +197 -183
  59. package/cjs/Core/ParticlesManager.js +363 -0
  60. package/cjs/Core/RenderManager.js +303 -0
  61. package/cjs/Core/Retina.js +6 -6
  62. package/cjs/Core/Utils/Constants.js +2 -2
  63. package/cjs/Core/Utils/EventListeners.js +67 -63
  64. package/cjs/Core/Utils/PluginManager.js +145 -0
  65. package/cjs/Core/Utils/Ranges.js +29 -10
  66. package/cjs/Core/Utils/SpatialHashGrid.js +102 -0
  67. package/cjs/Core/Utils/Vectors.js +17 -18
  68. package/cjs/Options/Classes/AnimatableColor.js +1 -0
  69. package/cjs/Options/Classes/AnimationOptions.js +8 -0
  70. package/cjs/Options/Classes/Background/Background.js +6 -0
  71. package/cjs/Options/Classes/ColorAnimation.js +12 -1
  72. package/cjs/Options/Classes/FullScreen/FullScreen.js +2 -0
  73. package/cjs/Options/Classes/HslAnimation.js +4 -5
  74. package/cjs/Options/Classes/Options.js +67 -8
  75. package/cjs/Options/Classes/OptionsColor.js +1 -0
  76. package/cjs/Options/Classes/Particles/Bounce/ParticlesBounce.js +2 -0
  77. package/cjs/Options/Classes/Particles/Effect/Effect.js +3 -4
  78. package/cjs/Options/Classes/Particles/Fill.js +28 -0
  79. package/cjs/Options/Classes/Particles/Move/Move.js +17 -3
  80. package/cjs/Options/Classes/Particles/Move/MoveAngle.js +2 -0
  81. package/cjs/Options/Classes/Particles/Move/MoveCenter.js +4 -0
  82. package/cjs/Options/Classes/Particles/Move/MoveGravity.js +4 -0
  83. package/cjs/Options/Classes/Particles/Move/OutModes.js +5 -0
  84. package/cjs/Options/Classes/Particles/Move/Path/MovePath.js +5 -0
  85. package/cjs/Options/Classes/Particles/Move/Spin.js +3 -0
  86. package/cjs/Options/Classes/Particles/Number/ParticlesDensity.js +3 -0
  87. package/cjs/Options/Classes/Particles/Number/ParticlesNumber.js +3 -0
  88. package/cjs/Options/Classes/Particles/Number/ParticlesNumberLimit.js +2 -0
  89. package/cjs/Options/Classes/Particles/Opacity/Opacity.js +1 -0
  90. package/cjs/Options/Classes/Particles/Opacity/OpacityAnimation.js +1 -0
  91. package/cjs/Options/Classes/Particles/ParticlesOptions.js +29 -9
  92. package/cjs/Options/Classes/Particles/Shape/Shape.js +3 -4
  93. package/cjs/Options/Classes/Particles/Size/Size.js +1 -0
  94. package/cjs/Options/Classes/Particles/Size/SizeAnimation.js +1 -0
  95. package/cjs/Options/Classes/Particles/Stroke.js +3 -0
  96. package/cjs/Options/Classes/Particles/ZIndex/ZIndex.js +3 -0
  97. package/cjs/Options/Classes/ResizeEvent.js +2 -0
  98. package/cjs/Options/Classes/ValueWithRandom.js +3 -4
  99. package/cjs/Utils/CanvasUtils.js +44 -51
  100. package/cjs/Utils/ColorUtils.js +51 -40
  101. package/cjs/Utils/EventDispatcher.js +1 -0
  102. package/cjs/Utils/LogUtils.js +1 -0
  103. package/cjs/Utils/MathUtils.js +12 -7
  104. package/cjs/Utils/OptionsUtils.js +2 -2
  105. package/cjs/Utils/Utils.js +109 -31
  106. package/cjs/exports.js +1 -2
  107. package/dist_browser_Core_Container_js.js +30 -20
  108. package/esm/Core/CanvasManager.js +303 -0
  109. package/esm/Core/Container.js +134 -101
  110. package/esm/Core/Engine.js +29 -162
  111. package/esm/Core/Particle.js +197 -183
  112. package/esm/Core/ParticlesManager.js +363 -0
  113. package/esm/Core/RenderManager.js +303 -0
  114. package/esm/Core/Retina.js +6 -6
  115. package/esm/Core/Utils/Constants.js +2 -2
  116. package/esm/Core/Utils/EventListeners.js +67 -63
  117. package/esm/Core/Utils/PluginManager.js +145 -0
  118. package/esm/Core/Utils/Ranges.js +29 -10
  119. package/esm/Core/Utils/SpatialHashGrid.js +102 -0
  120. package/esm/Core/Utils/Vectors.js +17 -18
  121. package/esm/Options/Classes/AnimatableColor.js +1 -0
  122. package/esm/Options/Classes/AnimationOptions.js +8 -0
  123. package/esm/Options/Classes/Background/Background.js +6 -0
  124. package/esm/Options/Classes/ColorAnimation.js +12 -1
  125. package/esm/Options/Classes/FullScreen/FullScreen.js +2 -0
  126. package/esm/Options/Classes/HslAnimation.js +4 -5
  127. package/esm/Options/Classes/Options.js +67 -8
  128. package/esm/Options/Classes/OptionsColor.js +1 -0
  129. package/esm/Options/Classes/Particles/Bounce/ParticlesBounce.js +2 -0
  130. package/esm/Options/Classes/Particles/Effect/Effect.js +3 -4
  131. package/esm/Options/Classes/Particles/Fill.js +28 -0
  132. package/esm/Options/Classes/Particles/Move/Move.js +17 -3
  133. package/esm/Options/Classes/Particles/Move/MoveAngle.js +2 -0
  134. package/esm/Options/Classes/Particles/Move/MoveCenter.js +4 -0
  135. package/esm/Options/Classes/Particles/Move/MoveGravity.js +4 -0
  136. package/esm/Options/Classes/Particles/Move/OutModes.js +5 -0
  137. package/esm/Options/Classes/Particles/Move/Path/MovePath.js +5 -0
  138. package/esm/Options/Classes/Particles/Move/Spin.js +3 -0
  139. package/esm/Options/Classes/Particles/Number/ParticlesDensity.js +3 -0
  140. package/esm/Options/Classes/Particles/Number/ParticlesNumber.js +3 -0
  141. package/esm/Options/Classes/Particles/Number/ParticlesNumberLimit.js +2 -0
  142. package/esm/Options/Classes/Particles/Opacity/Opacity.js +1 -0
  143. package/esm/Options/Classes/Particles/Opacity/OpacityAnimation.js +1 -0
  144. package/esm/Options/Classes/Particles/ParticlesOptions.js +29 -9
  145. package/esm/Options/Classes/Particles/Shape/Shape.js +3 -4
  146. package/esm/Options/Classes/Particles/Size/Size.js +1 -0
  147. package/esm/Options/Classes/Particles/Size/SizeAnimation.js +1 -0
  148. package/esm/Options/Classes/Particles/Stroke.js +3 -0
  149. package/esm/Options/Classes/Particles/ZIndex/ZIndex.js +3 -0
  150. package/esm/Options/Classes/ResizeEvent.js +2 -0
  151. package/esm/Options/Classes/ValueWithRandom.js +3 -4
  152. package/esm/Utils/CanvasUtils.js +44 -51
  153. package/esm/Utils/ColorUtils.js +51 -40
  154. package/esm/Utils/EventDispatcher.js +1 -0
  155. package/esm/Utils/LogUtils.js +1 -0
  156. package/esm/Utils/MathUtils.js +12 -7
  157. package/esm/Utils/OptionsUtils.js +2 -2
  158. package/esm/Utils/Utils.js +109 -31
  159. package/esm/exports.js +1 -2
  160. package/package.json +1 -1
  161. package/report.html +84 -29
  162. package/scripts/install.js +4 -20
  163. package/tsparticles.engine.js +98 -86
  164. package/tsparticles.engine.min.js +2 -2
  165. package/types/Core/CanvasManager.d.ts +39 -0
  166. package/types/Core/Container.d.ts +29 -14
  167. package/types/Core/Engine.d.ts +2 -61
  168. package/types/Core/Interfaces/IColorManager.d.ts +0 -1
  169. package/types/Core/Interfaces/IContainerPlugin.d.ts +10 -8
  170. package/types/Core/Interfaces/IDrawParticleParams.d.ts +2 -1
  171. package/types/Core/Interfaces/IPalette.d.ts +7 -0
  172. package/types/Core/Interfaces/IParticleOpacityData.d.ts +1 -0
  173. package/types/Core/Interfaces/IParticleRetinaProps.d.ts +4 -4
  174. package/types/Core/Interfaces/IParticleUpdater.d.ts +2 -1
  175. package/types/Core/Interfaces/IParticleValueAnimation.d.ts +3 -3
  176. package/types/Core/Interfaces/IShapeDrawData.d.ts +10 -1
  177. package/types/Core/Interfaces/IShapeDrawer.d.ts +0 -1
  178. package/types/Core/Interfaces/IShapeValues.d.ts +0 -1
  179. package/types/Core/Particle.d.ts +7 -11
  180. package/types/Core/{Particles.d.ts → ParticlesManager.d.ts} +15 -14
  181. package/types/Core/RenderManager.d.ts +49 -0
  182. package/types/Core/Retina.d.ts +0 -2
  183. package/types/Core/Utils/Constants.d.ts +2 -2
  184. package/types/Core/Utils/PluginManager.d.ts +62 -0
  185. package/types/Core/Utils/Ranges.d.ts +4 -1
  186. package/types/Core/Utils/SpatialHashGrid.d.ts +25 -0
  187. package/types/Core/Utils/Vectors.d.ts +8 -10
  188. package/types/Options/Classes/ColorAnimation.d.ts +3 -1
  189. package/types/Options/Classes/HslAnimation.d.ts +3 -4
  190. package/types/Options/Classes/Options.d.ts +5 -3
  191. package/types/Options/Classes/Particles/Effect/Effect.d.ts +0 -1
  192. package/types/Options/Classes/Particles/Fill.d.ts +12 -0
  193. package/types/Options/Classes/Particles/Move/Move.d.ts +0 -2
  194. package/types/Options/Classes/Particles/ParticlesOptions.d.ts +5 -5
  195. package/types/Options/Classes/Particles/Shape/Shape.d.ts +0 -1
  196. package/types/Options/Classes/ValueWithRandom.d.ts +0 -1
  197. package/types/Options/Interfaces/IColorAnimation.d.ts +2 -0
  198. package/types/Options/Interfaces/IOptions.d.ts +1 -0
  199. package/types/Options/Interfaces/Particles/Effect/IEffect.d.ts +0 -1
  200. package/types/Options/Interfaces/Particles/IFill.d.ts +9 -0
  201. package/types/Options/Interfaces/Particles/IParticlesOptions.d.ts +2 -2
  202. package/types/Options/Interfaces/Particles/IStroke.d.ts +2 -2
  203. package/types/Options/Interfaces/Particles/Move/IMove.d.ts +0 -2
  204. package/types/Options/Interfaces/Particles/Shape/IShape.d.ts +0 -1
  205. package/types/Types/CanvasContextType.d.ts +1 -0
  206. package/types/Types/EngineInitializers.d.ts +6 -3
  207. package/types/Utils/CanvasUtils.d.ts +13 -16
  208. package/types/Utils/ColorUtils.d.ts +11 -10
  209. package/types/Utils/LogUtils.d.ts +1 -0
  210. package/types/Utils/MathUtils.d.ts +2 -0
  211. package/types/Utils/OptionsUtils.d.ts +2 -2
  212. package/types/Utils/Utils.d.ts +8 -1
  213. package/types/export-types.d.ts +7 -7
  214. package/types/exports.d.ts +1 -2
  215. package/umd/Core/CanvasManager.js +317 -0
  216. package/umd/Core/Container.js +134 -101
  217. package/umd/Core/Engine.js +28 -161
  218. package/umd/Core/Particle.js +198 -184
  219. package/umd/Core/{Particles.js → ParticlesManager.js} +186 -167
  220. package/umd/Core/RenderManager.js +317 -0
  221. package/umd/Core/Retina.js +6 -6
  222. package/umd/Core/Utils/Constants.js +3 -3
  223. package/umd/Core/Utils/EventListeners.js +67 -63
  224. package/umd/Core/Utils/PluginManager.js +159 -0
  225. package/umd/Core/Utils/Ranges.js +28 -9
  226. package/umd/Core/Utils/SpatialHashGrid.js +116 -0
  227. package/umd/Core/Utils/Vectors.js +17 -18
  228. package/umd/Options/Classes/AnimatableColor.js +1 -0
  229. package/umd/Options/Classes/AnimationOptions.js +8 -0
  230. package/umd/Options/Classes/Background/Background.js +6 -0
  231. package/umd/Options/Classes/ColorAnimation.js +12 -1
  232. package/umd/Options/Classes/FullScreen/FullScreen.js +2 -0
  233. package/umd/Options/Classes/HslAnimation.js +5 -6
  234. package/umd/Options/Classes/Options.js +67 -8
  235. package/umd/Options/Classes/OptionsColor.js +1 -0
  236. package/umd/Options/Classes/Particles/Bounce/ParticlesBounce.js +2 -0
  237. package/umd/Options/Classes/Particles/Effect/Effect.js +3 -4
  238. package/umd/Options/Classes/Particles/Fill.js +42 -0
  239. package/umd/Options/Classes/Particles/Move/Move.js +18 -4
  240. package/umd/Options/Classes/Particles/Move/MoveAngle.js +2 -0
  241. package/umd/Options/Classes/Particles/Move/MoveCenter.js +4 -0
  242. package/umd/Options/Classes/Particles/Move/MoveGravity.js +4 -0
  243. package/umd/Options/Classes/Particles/Move/OutModes.js +5 -0
  244. package/umd/Options/Classes/Particles/Move/Path/MovePath.js +5 -0
  245. package/umd/Options/Classes/Particles/Move/Spin.js +3 -0
  246. package/umd/Options/Classes/Particles/Number/ParticlesDensity.js +3 -0
  247. package/umd/Options/Classes/Particles/Number/ParticlesNumber.js +3 -0
  248. package/umd/Options/Classes/Particles/Number/ParticlesNumberLimit.js +2 -0
  249. package/umd/Options/Classes/Particles/Opacity/Opacity.js +1 -0
  250. package/umd/Options/Classes/Particles/Opacity/OpacityAnimation.js +1 -0
  251. package/umd/Options/Classes/Particles/ParticlesOptions.js +30 -10
  252. package/umd/Options/Classes/Particles/Shape/Shape.js +3 -4
  253. package/umd/Options/Classes/Particles/Size/Size.js +1 -0
  254. package/umd/Options/Classes/Particles/Size/SizeAnimation.js +1 -0
  255. package/umd/Options/Classes/Particles/Stroke.js +3 -0
  256. package/umd/Options/Classes/Particles/ZIndex/ZIndex.js +3 -0
  257. package/umd/Options/Classes/ResizeEvent.js +2 -0
  258. package/umd/Options/Classes/ValueWithRandom.js +3 -4
  259. package/umd/Utils/CanvasUtils.js +44 -53
  260. package/umd/Utils/ColorUtils.js +51 -39
  261. package/umd/Utils/EventDispatcher.js +1 -0
  262. package/umd/Utils/LogUtils.js +1 -0
  263. package/umd/Utils/MathUtils.js +14 -7
  264. package/umd/Utils/OptionsUtils.js +2 -2
  265. package/umd/Utils/Utils.js +111 -32
  266. package/umd/exports.js +2 -3
  267. package/794.min.js +0 -2
  268. package/794.min.js.LICENSE.txt +0 -1
  269. package/browser/Core/Canvas.js +0 -469
  270. package/browser/Core/Particles.js +0 -344
  271. package/browser/Core/Utils/Point.js +0 -6
  272. package/browser/Core/Utils/QuadTree.js +0 -59
  273. package/browser/Options/Classes/Particles/Move/MoveAttract.js +0 -33
  274. package/cjs/Core/Canvas.js +0 -469
  275. package/cjs/Core/Particles.js +0 -344
  276. package/cjs/Core/Utils/Point.js +0 -6
  277. package/cjs/Core/Utils/QuadTree.js +0 -59
  278. package/cjs/Options/Classes/Particles/Move/MoveAttract.js +0 -33
  279. package/esm/Core/Canvas.js +0 -469
  280. package/esm/Core/Particles.js +0 -344
  281. package/esm/Core/Utils/Point.js +0 -6
  282. package/esm/Core/Utils/QuadTree.js +0 -59
  283. package/esm/Options/Classes/Particles/Move/MoveAttract.js +0 -33
  284. package/tsparticles.engine.min.js.LICENSE.txt +0 -1
  285. package/types/Core/Canvas.d.ts +0 -55
  286. package/types/Core/Interfaces/IMovePathGenerator.d.ts +0 -10
  287. package/types/Core/Interfaces/IParticleMover.d.ts +0 -7
  288. package/types/Core/Utils/Point.d.ts +0 -7
  289. package/types/Core/Utils/QuadTree.d.ts +0 -18
  290. package/types/Options/Classes/Particles/Move/MoveAttract.d.ts +0 -12
  291. package/types/Options/Interfaces/Particles/Move/IMoveAttract.d.ts +0 -7
  292. package/umd/Core/Canvas.js +0 -483
  293. package/umd/Core/Utils/Point.js +0 -20
  294. package/umd/Core/Utils/QuadTree.js +0 -73
  295. package/umd/Options/Classes/Particles/Move/MoveAttract.js +0 -47
  296. /package/browser/Core/Interfaces/{IMovePathGenerator.js → IPalette.js} +0 -0
  297. /package/browser/{Core/Interfaces/IParticleMover.js → Options/Interfaces/Particles/IFill.js} +0 -0
  298. /package/browser/{Options/Interfaces/Particles/Move/IMoveAttract.js → Types/CanvasContextType.js} +0 -0
  299. /package/cjs/Core/Interfaces/{IMovePathGenerator.js → IPalette.js} +0 -0
  300. /package/cjs/{Core/Interfaces/IParticleMover.js → Options/Interfaces/Particles/IFill.js} +0 -0
  301. /package/cjs/{Options/Interfaces/Particles/Move/IMoveAttract.js → Types/CanvasContextType.js} +0 -0
  302. /package/esm/Core/Interfaces/{IMovePathGenerator.js → IPalette.js} +0 -0
  303. /package/esm/{Core/Interfaces/IParticleMover.js → Options/Interfaces/Particles/IFill.js} +0 -0
  304. /package/esm/{Options/Interfaces/Particles/Move/IMoveAttract.js → Types/CanvasContextType.js} +0 -0
  305. /package/umd/Core/Interfaces/{IMovePathGenerator.js → IPalette.js} +0 -0
  306. /package/umd/{Core/Interfaces/IParticleMover.js → Options/Interfaces/Particles/IFill.js} +0 -0
  307. /package/umd/{Options/Interfaces/Particles/Move/IMoveAttract.js → Types/CanvasContextType.js} +0 -0
@@ -0,0 +1,303 @@
1
+ import { cloneStyle, getFullScreenStyle, safeMatchMedia, safeMutationObserver } from "../Utils/Utils.js";
2
+ import { defaultZoom, generatedAttribute, half } from "./Utils/Constants.js";
3
+ import { getStyleFromRgb, rangeColorToRgb } from "../Utils/ColorUtils.js";
4
+ import { RenderManager } from "./RenderManager.js";
5
+ function setStyle(canvas, style, important = false) {
6
+ if (!style) {
7
+ return;
8
+ }
9
+ const element = canvas, elementStyle = element.style, keys = new Set();
10
+ for (let i = 0; i < elementStyle.length; i++) {
11
+ const key = elementStyle.item(i);
12
+ if (!key) {
13
+ continue;
14
+ }
15
+ keys.add(key);
16
+ }
17
+ for (let i = 0; i < style.length; i++) {
18
+ const key = style.item(i);
19
+ if (!key) {
20
+ continue;
21
+ }
22
+ keys.add(key);
23
+ }
24
+ for (const key of keys) {
25
+ const value = style.getPropertyValue(key);
26
+ if (value) {
27
+ elementStyle.setProperty(key, value, important ? "important" : "");
28
+ }
29
+ else {
30
+ elementStyle.removeProperty(key);
31
+ }
32
+ }
33
+ }
34
+ export class CanvasManager {
35
+ element;
36
+ render;
37
+ size;
38
+ zoom = defaultZoom;
39
+ _container;
40
+ _generated;
41
+ _mutationObserver;
42
+ _originalStyle;
43
+ _pluginManager;
44
+ _pointerEvents;
45
+ _resizePlugins;
46
+ _standardSize;
47
+ _zoomCenter;
48
+ constructor(pluginManager, container) {
49
+ this._pluginManager = pluginManager;
50
+ this._container = container;
51
+ this.render = new RenderManager(pluginManager, container, this);
52
+ this._standardSize = {
53
+ height: 0,
54
+ width: 0,
55
+ };
56
+ const pxRatio = container.retina.pixelRatio, stdSize = this._standardSize;
57
+ this.size = {
58
+ height: stdSize.height * pxRatio,
59
+ width: stdSize.width * pxRatio,
60
+ };
61
+ this._generated = false;
62
+ this._resizePlugins = [];
63
+ this._pointerEvents = "none";
64
+ }
65
+ get _fullScreen() {
66
+ return this._container.actualOptions.fullScreen.enable;
67
+ }
68
+ destroy() {
69
+ this.stop();
70
+ if (this._generated) {
71
+ const element = this.element;
72
+ element?.remove();
73
+ this.element = undefined;
74
+ }
75
+ else {
76
+ this._resetOriginalStyle();
77
+ }
78
+ this.render.destroy();
79
+ this._resizePlugins = [];
80
+ }
81
+ getZoomCenter() {
82
+ const pxRatio = this._container.retina.pixelRatio, { width, height } = this.size;
83
+ if (this._zoomCenter) {
84
+ return this._zoomCenter;
85
+ }
86
+ return {
87
+ x: (width * half) / pxRatio,
88
+ y: (height * half) / pxRatio,
89
+ };
90
+ }
91
+ init() {
92
+ this._safeMutationObserver(obs => {
93
+ obs.disconnect();
94
+ });
95
+ this._mutationObserver = safeMutationObserver(records => {
96
+ for (const record of records) {
97
+ if (record.type === "attributes" && record.attributeName === "style") {
98
+ this._repairStyle();
99
+ }
100
+ }
101
+ });
102
+ this.resize();
103
+ this._initStyle();
104
+ this.initBackground();
105
+ this._safeMutationObserver(obs => {
106
+ if (!this.element || !(this.element instanceof Node)) {
107
+ return;
108
+ }
109
+ obs.observe(this.element, { attributes: true });
110
+ });
111
+ this.initPlugins();
112
+ this.render.init();
113
+ }
114
+ initBackground() {
115
+ const { _container } = this, options = _container.actualOptions, background = options.background, element = this.element;
116
+ if (!element) {
117
+ return;
118
+ }
119
+ const elementStyle = element.style, color = rangeColorToRgb(this._pluginManager, background.color);
120
+ if (color) {
121
+ elementStyle.backgroundColor = getStyleFromRgb(color, _container.hdr, background.opacity);
122
+ }
123
+ else {
124
+ elementStyle.backgroundColor = "";
125
+ }
126
+ elementStyle.backgroundImage = background.image || "";
127
+ elementStyle.backgroundPosition = background.position || "";
128
+ elementStyle.backgroundRepeat = background.repeat || "";
129
+ elementStyle.backgroundSize = background.size || "";
130
+ }
131
+ initPlugins() {
132
+ this._resizePlugins = [];
133
+ for (const plugin of this._container.plugins) {
134
+ if (plugin.resize) {
135
+ this._resizePlugins.push(plugin);
136
+ }
137
+ }
138
+ }
139
+ loadCanvas(canvas) {
140
+ if (this._generated && this.element) {
141
+ this.element.remove();
142
+ }
143
+ const container = this._container;
144
+ this._generated =
145
+ generatedAttribute in canvas.dataset ? canvas.dataset[generatedAttribute] === "true" : this._generated;
146
+ this.element = canvas;
147
+ this.element.ariaHidden = "true";
148
+ this._originalStyle = cloneStyle(this.element.style);
149
+ const standardSize = this._standardSize;
150
+ standardSize.height = canvas.offsetHeight;
151
+ standardSize.width = canvas.offsetWidth;
152
+ const pxRatio = this._container.retina.pixelRatio, retinaSize = this.size;
153
+ canvas.height = retinaSize.height = standardSize.height * pxRatio;
154
+ canvas.width = retinaSize.width = standardSize.width * pxRatio;
155
+ const canSupportHdrQuery = safeMatchMedia("(color-gamut: p3)");
156
+ this.render.setContextSettings({
157
+ alpha: true,
158
+ colorSpace: canSupportHdrQuery?.matches && container.hdr ? "display-p3" : "srgb",
159
+ desynchronized: true,
160
+ willReadFrequently: false,
161
+ });
162
+ this.render.setContext(this.element.getContext("2d", this.render.settings));
163
+ this._safeMutationObserver(obs => {
164
+ obs.disconnect();
165
+ });
166
+ container.retina.init();
167
+ this.initBackground();
168
+ this._safeMutationObserver(obs => {
169
+ if (!this.element || !(this.element instanceof Node)) {
170
+ return;
171
+ }
172
+ obs.observe(this.element, { attributes: true });
173
+ });
174
+ }
175
+ resize() {
176
+ if (!this.element) {
177
+ return false;
178
+ }
179
+ const container = this._container, currentSize = container.canvas._standardSize, newSize = {
180
+ width: this.element.offsetWidth,
181
+ height: this.element.offsetHeight,
182
+ }, pxRatio = container.retina.pixelRatio, retinaSize = {
183
+ width: newSize.width * pxRatio,
184
+ height: newSize.height * pxRatio,
185
+ };
186
+ if (newSize.height === currentSize.height &&
187
+ newSize.width === currentSize.width &&
188
+ retinaSize.height === this.element.height &&
189
+ retinaSize.width === this.element.width) {
190
+ return false;
191
+ }
192
+ const oldSize = { ...currentSize };
193
+ currentSize.height = newSize.height;
194
+ currentSize.width = newSize.width;
195
+ const canvasSize = this.size;
196
+ this.element.width = canvasSize.width = retinaSize.width;
197
+ this.element.height = canvasSize.height = retinaSize.height;
198
+ if (this._container.started) {
199
+ container.particles.setResizeFactor({
200
+ width: currentSize.width / oldSize.width,
201
+ height: currentSize.height / oldSize.height,
202
+ });
203
+ }
204
+ return true;
205
+ }
206
+ setPointerEvents(type) {
207
+ const element = this.element;
208
+ if (!element) {
209
+ return;
210
+ }
211
+ this._pointerEvents = type;
212
+ this._repairStyle();
213
+ }
214
+ setZoom(zoomLevel, center) {
215
+ this.zoom = zoomLevel;
216
+ this._zoomCenter = center;
217
+ }
218
+ stop() {
219
+ this._safeMutationObserver(obs => {
220
+ obs.disconnect();
221
+ });
222
+ this._mutationObserver = undefined;
223
+ this.render.stop();
224
+ }
225
+ async windowResize() {
226
+ if (!this.element || !this.resize()) {
227
+ return;
228
+ }
229
+ const container = this._container, needsRefresh = container.updateActualOptions();
230
+ container.particles.setDensity();
231
+ this._applyResizePlugins();
232
+ if (needsRefresh) {
233
+ await container.refresh();
234
+ }
235
+ }
236
+ _applyResizePlugins = () => {
237
+ for (const plugin of this._resizePlugins) {
238
+ plugin.resize?.();
239
+ }
240
+ };
241
+ _initStyle = () => {
242
+ const element = this.element, options = this._container.actualOptions;
243
+ if (!element) {
244
+ return;
245
+ }
246
+ if (this._fullScreen) {
247
+ this._setFullScreenStyle();
248
+ }
249
+ else {
250
+ this._resetOriginalStyle();
251
+ }
252
+ for (const key in options.style) {
253
+ if (!key || !(key in options.style)) {
254
+ continue;
255
+ }
256
+ const value = options.style[key];
257
+ if (!value) {
258
+ continue;
259
+ }
260
+ element.style.setProperty(key, value, "important");
261
+ }
262
+ };
263
+ _repairStyle = () => {
264
+ const element = this.element;
265
+ if (!element) {
266
+ return;
267
+ }
268
+ this._safeMutationObserver(observer => {
269
+ observer.disconnect();
270
+ });
271
+ this._initStyle();
272
+ this.initBackground();
273
+ const pointerEvents = this._pointerEvents;
274
+ element.style.pointerEvents = pointerEvents;
275
+ element.setAttribute("pointer-events", pointerEvents);
276
+ this._safeMutationObserver(observer => {
277
+ if (!(element instanceof Node)) {
278
+ return;
279
+ }
280
+ observer.observe(element, { attributes: true });
281
+ });
282
+ };
283
+ _resetOriginalStyle = () => {
284
+ const element = this.element, originalStyle = this._originalStyle;
285
+ if (!element || !originalStyle) {
286
+ return;
287
+ }
288
+ setStyle(element, originalStyle, true);
289
+ };
290
+ _safeMutationObserver = callback => {
291
+ if (!this._mutationObserver) {
292
+ return;
293
+ }
294
+ callback(this._mutationObserver);
295
+ };
296
+ _setFullScreenStyle = () => {
297
+ const element = this.element;
298
+ if (!element) {
299
+ return;
300
+ }
301
+ setStyle(element, getFullScreenStyle(this._container.actualOptions.fullScreen.zIndex), true);
302
+ };
303
+ }
@@ -1,10 +1,10 @@
1
1
  import { animate, cancelAnimation, getRangeValue } from "../Utils/MathUtils.js";
2
- import { defaultFps, defaultFpsLimit, millisecondsToSeconds, minFpsLimit, removeDeleteCount, removeMinIndex, } from "./Utils/Constants.js";
3
- import { Canvas } from "./Canvas.js";
2
+ import { defaultFps, defaultFpsLimit, millisecondsToSeconds, minFpsLimit } from "./Utils/Constants.js";
3
+ import { CanvasManager } from "./CanvasManager.js";
4
4
  import { EventListeners } from "./Utils/EventListeners.js";
5
5
  import { EventType } from "../Enums/Types/EventType.js";
6
6
  import { Options } from "../Options/Classes/Options.js";
7
- import { Particles } from "./Particles.js";
7
+ import { ParticlesManager } from "./ParticlesManager.js";
8
8
  import { Retina } from "./Retina.js";
9
9
  import { getLogger } from "../Utils/LogUtils.js";
10
10
  import { loadOptions } from "../Utils/OptionsUtils.js";
@@ -15,44 +15,52 @@ function updateDelta(delta, value, fpsLimit = defaultFps, smooth = false) {
15
15
  delta.value = value;
16
16
  delta.factor = smooth ? defaultFps / fpsLimit : (defaultFps * value) / millisecondsToSeconds;
17
17
  }
18
- function loadContainerOptions(engine, container, ...sourceOptionsArr) {
19
- const options = new Options(engine, container);
18
+ function loadContainerOptions(pluginManager, container, ...sourceOptionsArr) {
19
+ const options = new Options(pluginManager, container);
20
20
  loadOptions(options, ...sourceOptionsArr);
21
21
  return options;
22
22
  }
23
23
  export class Container {
24
- constructor(engine, id, sourceOptions) {
25
- this._delta = { value: 0, factor: 0 };
26
- this._nextFrame = (timestamp) => {
27
- try {
28
- if (!this._smooth &&
29
- this._lastFrameTime !== undefined &&
30
- timestamp < this._lastFrameTime + millisecondsToSeconds / this.fpsLimit) {
31
- this.draw(false);
32
- return;
33
- }
34
- this._lastFrameTime ??= timestamp;
35
- updateDelta(this._delta, timestamp - this._lastFrameTime, this.fpsLimit, this._smooth);
36
- this.addLifeTime(this._delta.value);
37
- this._lastFrameTime = timestamp;
38
- if (this._delta.value > millisecondsToSeconds) {
39
- this.draw(false);
40
- return;
41
- }
42
- this.canvas.drawParticles(this._delta);
43
- if (!this.alive()) {
44
- this.destroy();
45
- return;
46
- }
47
- if (this.animationStatus) {
48
- this.draw(false);
49
- }
50
- }
51
- catch (e) {
52
- getLogger().error("error in animation loop", e);
53
- }
54
- };
55
- this._engine = engine;
24
+ actualOptions;
25
+ canvas;
26
+ destroyed;
27
+ effectDrawers;
28
+ fpsLimit;
29
+ hdr;
30
+ id;
31
+ pageHidden;
32
+ particleCreatedPlugins;
33
+ particleDestroyedPlugins;
34
+ particlePositionPlugins;
35
+ particleUpdaters;
36
+ particles;
37
+ plugins;
38
+ retina;
39
+ shapeDrawers;
40
+ started;
41
+ zLayers;
42
+ _delay;
43
+ _delayTimeout;
44
+ _delta = { value: 0, factor: 0 };
45
+ _dispatchCallback;
46
+ _drawAnimationFrame;
47
+ _duration;
48
+ _eventListeners;
49
+ _firstStart;
50
+ _initialSourceOptions;
51
+ _lastFrameTime;
52
+ _lifeTime;
53
+ _onDestroy;
54
+ _options;
55
+ _paused;
56
+ _pluginManager;
57
+ _smooth;
58
+ _sourceOptions;
59
+ constructor(params) {
60
+ const { dispatchCallback, pluginManager, id, onDestroy, sourceOptions } = params;
61
+ this._pluginManager = pluginManager;
62
+ this._dispatchCallback = dispatchCallback;
63
+ this._onDestroy = onDestroy;
56
64
  this.id = Symbol(id);
57
65
  this.fpsLimit = 120;
58
66
  this.hdr = false;
@@ -69,17 +77,20 @@ export class Container {
69
77
  this.pageHidden = false;
70
78
  this._sourceOptions = sourceOptions;
71
79
  this._initialSourceOptions = sourceOptions;
72
- this.retina = new Retina(this);
73
- this.canvas = new Canvas(this, this._engine);
74
- this.particles = new Particles(this._engine, this);
75
- this.pathGenerators = new Map();
76
- this.plugins = [];
77
80
  this.effectDrawers = new Map();
78
81
  this.shapeDrawers = new Map();
79
- this._options = loadContainerOptions(this._engine, this);
80
- this.actualOptions = loadContainerOptions(this._engine, this);
82
+ this.particleUpdaters = [];
83
+ this.retina = new Retina(this);
84
+ this.canvas = new CanvasManager(this._pluginManager, this);
85
+ this.particles = new ParticlesManager(this._pluginManager, this);
86
+ this.plugins = [];
87
+ this.particleDestroyedPlugins = [];
88
+ this.particleCreatedPlugins = [];
89
+ this.particlePositionPlugins = [];
90
+ this._options = loadContainerOptions(this._pluginManager, this);
91
+ this.actualOptions = loadContainerOptions(this._pluginManager, this);
81
92
  this._eventListeners = new EventListeners(this);
82
- this._engine.dispatchEvent(EventType.containerBuilt, { container: this });
93
+ this.dispatchEvent(EventType.containerBuilt);
83
94
  }
84
95
  get animationStatus() {
85
96
  return !this._paused && !this.pageHidden && guardCheck(this);
@@ -93,13 +104,6 @@ export class Container {
93
104
  addLifeTime(value) {
94
105
  this._lifeTime += value;
95
106
  }
96
- addPath(key, generator, override = false) {
97
- if (!guardCheck(this) || (!override && this.pathGenerators.has(key))) {
98
- return false;
99
- }
100
- this.pathGenerators.set(key, generator);
101
- return true;
102
- }
103
107
  alive() {
104
108
  return !this._duration || this._lifeTime <= this._duration;
105
109
  }
@@ -110,42 +114,41 @@ export class Container {
110
114
  this.stop();
111
115
  this.particles.destroy();
112
116
  this.canvas.destroy();
113
- for (const effectDrawer of this.effectDrawers.values()) {
117
+ for (const [, effectDrawer] of this.effectDrawers) {
114
118
  effectDrawer.destroy?.(this);
115
119
  }
116
- this.effectDrawers.clear();
117
- for (const shapeDrawer of this.shapeDrawers.values()) {
120
+ for (const [, shapeDrawer] of this.shapeDrawers) {
118
121
  shapeDrawer.destroy?.(this);
119
122
  }
120
- this.shapeDrawers.clear();
121
123
  for (const plugin of this.plugins) {
122
124
  plugin.destroy?.();
123
125
  }
126
+ this.effectDrawers = new Map();
127
+ this.shapeDrawers = new Map();
128
+ this.particleUpdaters = [];
124
129
  this.plugins.length = 0;
125
- this._engine.clearPlugins(this);
130
+ this._pluginManager.clearPlugins(this);
126
131
  this.destroyed = true;
127
- if (remove) {
128
- const mainArr = this._engine.items, idx = mainArr.indexOf(this);
129
- if (idx >= removeMinIndex) {
130
- mainArr.splice(idx, removeDeleteCount);
131
- }
132
- }
133
- this._engine.dispatchEvent(EventType.containerDestroyed, { container: this });
132
+ this._onDestroy(remove);
133
+ this.dispatchEvent(EventType.containerDestroyed);
134
+ }
135
+ dispatchEvent(type, data) {
136
+ this._dispatchCallback(type, {
137
+ container: this,
138
+ data,
139
+ });
134
140
  }
135
141
  draw(force) {
136
142
  if (!guardCheck(this)) {
137
143
  return;
138
144
  }
139
145
  let refreshTime = force;
140
- const frame = (timestamp) => {
146
+ this._drawAnimationFrame = animate((timestamp) => {
141
147
  if (refreshTime) {
142
148
  this._lastFrameTime = undefined;
143
149
  refreshTime = false;
144
150
  }
145
151
  this._nextFrame(timestamp);
146
- };
147
- this._drawAnimationFrame = animate(timestamp => {
148
- frame(timestamp);
149
152
  });
150
153
  }
151
154
  async export(type, options = {}) {
@@ -166,34 +169,33 @@ export class Container {
166
169
  if (!guardCheck(this)) {
167
170
  return;
168
171
  }
169
- const effects = this._engine.getSupportedEffects();
170
- for (const type of effects) {
171
- const drawer = this._engine.getEffectDrawer(type);
172
- if (drawer) {
173
- this.effectDrawers.set(type, drawer);
174
- }
175
- }
176
- const shapes = this._engine.getSupportedShapes();
177
- for (const type of shapes) {
178
- const drawer = this._engine.getShapeDrawer(type);
179
- if (drawer) {
180
- this.shapeDrawers.set(type, drawer);
181
- }
182
- }
183
172
  const allContainerPlugins = new Map();
184
- for (const plugin of this._engine.plugins) {
173
+ for (const plugin of this._pluginManager.plugins) {
185
174
  const containerPlugin = await plugin.getPlugin(this);
186
175
  if (containerPlugin.preInit) {
187
176
  await containerPlugin.preInit();
188
177
  }
189
178
  allContainerPlugins.set(plugin, containerPlugin);
190
179
  }
191
- await this.particles.initPlugins();
192
- this._options = loadContainerOptions(this._engine, this, this._initialSourceOptions, this.sourceOptions);
193
- this.actualOptions = loadContainerOptions(this._engine, this, this._options);
180
+ await this.initDrawersAndUpdaters();
181
+ this._options = loadContainerOptions(this._pluginManager, this, this._initialSourceOptions, this.sourceOptions);
182
+ this.actualOptions = loadContainerOptions(this._pluginManager, this, this._options);
183
+ this.plugins.length = 0;
184
+ this.particleDestroyedPlugins.length = 0;
185
+ this.particleCreatedPlugins.length = 0;
186
+ this.particlePositionPlugins.length = 0;
194
187
  for (const [plugin, containerPlugin] of allContainerPlugins) {
195
188
  if (plugin.needsPlugin(this.actualOptions)) {
196
189
  this.plugins.push(containerPlugin);
190
+ if (containerPlugin.particleCreated) {
191
+ this.particleCreatedPlugins.push(containerPlugin);
192
+ }
193
+ if (containerPlugin.particleDestroyed) {
194
+ this.particleDestroyedPlugins.push(containerPlugin);
195
+ }
196
+ if (containerPlugin.particlePosition) {
197
+ this.particlePositionPlugins.push(containerPlugin);
198
+ }
197
199
  }
198
200
  }
199
201
  this.retina.init();
@@ -212,19 +214,19 @@ export class Container {
212
214
  for (const plugin of this.plugins) {
213
215
  await plugin.init?.();
214
216
  }
215
- for (const drawer of this.effectDrawers.values()) {
216
- await drawer.init?.(this);
217
- }
218
- for (const drawer of this.shapeDrawers.values()) {
219
- await drawer.init?.(this);
220
- }
221
- this._engine.dispatchEvent(EventType.containerInit, { container: this });
222
217
  await this.particles.init();
218
+ this.dispatchEvent(EventType.containerInit);
223
219
  this.particles.setDensity();
224
220
  for (const plugin of this.plugins) {
225
221
  plugin.particlesSetup?.();
226
222
  }
227
- this._engine.dispatchEvent(EventType.particlesSetup, { container: this });
223
+ this.dispatchEvent(EventType.particlesSetup);
224
+ }
225
+ async initDrawersAndUpdaters() {
226
+ const pluginManager = this._pluginManager;
227
+ this.effectDrawers = await pluginManager.getEffectDrawers(this, true);
228
+ this.shapeDrawers = await pluginManager.getShapeDrawers(this, true);
229
+ this.particleUpdaters = await pluginManager.getUpdaters(this, true);
228
230
  }
229
231
  pause() {
230
232
  if (!guardCheck(this)) {
@@ -243,7 +245,7 @@ export class Container {
243
245
  if (!this.pageHidden) {
244
246
  this._paused = true;
245
247
  }
246
- this._engine.dispatchEvent(EventType.containerPaused, { container: this });
248
+ this.dispatchEvent(EventType.containerPaused);
247
249
  }
248
250
  play(force) {
249
251
  if (!guardCheck(this)) {
@@ -264,7 +266,7 @@ export class Container {
264
266
  }
265
267
  }
266
268
  }
267
- this._engine.dispatchEvent(EventType.containerPlay, { container: this });
269
+ this.dispatchEvent(EventType.containerPlay);
268
270
  this.draw(needsUpdate ?? false);
269
271
  }
270
272
  async refresh() {
@@ -280,8 +282,8 @@ export class Container {
280
282
  }
281
283
  this._initialSourceOptions = sourceOptions;
282
284
  this._sourceOptions = sourceOptions;
283
- this._options = loadContainerOptions(this._engine, this, this._initialSourceOptions, this.sourceOptions);
284
- this.actualOptions = loadContainerOptions(this._engine, this, this._options);
285
+ this._options = loadContainerOptions(this._pluginManager, this, this._initialSourceOptions, this.sourceOptions);
286
+ this.actualOptions = loadContainerOptions(this._pluginManager, this, this._options);
285
287
  return this.refresh();
286
288
  }
287
289
  async start() {
@@ -296,7 +298,7 @@ export class Container {
296
298
  for (const plugin of this.plugins) {
297
299
  await plugin.start?.();
298
300
  }
299
- this._engine.dispatchEvent(EventType.containerStarted, { container: this });
301
+ this.dispatchEvent(EventType.containerStarted);
300
302
  this.play();
301
303
  resolve();
302
304
  };
@@ -320,9 +322,11 @@ export class Container {
320
322
  for (const plugin of this.plugins) {
321
323
  plugin.stop?.();
322
324
  }
323
- this.plugins.length = 0;
325
+ this.particleCreatedPlugins.length = 0;
326
+ this.particleDestroyedPlugins.length = 0;
327
+ this.particlePositionPlugins.length = 0;
324
328
  this._sourceOptions = this._options;
325
- this._engine.dispatchEvent(EventType.containerStopped, { container: this });
329
+ this.dispatchEvent(EventType.containerStopped);
326
330
  }
327
331
  updateActualOptions() {
328
332
  let refresh = false;
@@ -333,4 +337,33 @@ export class Container {
333
337
  }
334
338
  return refresh;
335
339
  }
340
+ _nextFrame = (timestamp) => {
341
+ try {
342
+ if (!this._smooth &&
343
+ this._lastFrameTime !== undefined &&
344
+ timestamp < this._lastFrameTime + millisecondsToSeconds / this.fpsLimit) {
345
+ this.draw(false);
346
+ return;
347
+ }
348
+ this._lastFrameTime ??= timestamp;
349
+ updateDelta(this._delta, timestamp - this._lastFrameTime, this.fpsLimit, this._smooth);
350
+ this.addLifeTime(this._delta.value);
351
+ this._lastFrameTime = timestamp;
352
+ if (this._delta.value > millisecondsToSeconds) {
353
+ this.draw(false);
354
+ return;
355
+ }
356
+ this.canvas.render.drawParticles(this._delta);
357
+ if (!this.alive()) {
358
+ this.destroy();
359
+ return;
360
+ }
361
+ if (this.animationStatus) {
362
+ this.draw(false);
363
+ }
364
+ }
365
+ catch (e) {
366
+ getLogger().error("error in animation loop", e);
367
+ }
368
+ };
336
369
  }