@xdy-npm/react-particle-backgrounds 1.0.0 → 1.0.2

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.
package/dist/index.mjs CHANGED
@@ -33,9 +33,9 @@ var DEFAULT_COLORS = [
33
33
  // src/themes/starline.ts
34
34
  var starlineTheme = {
35
35
  id: "starline",
36
- name: "Star Links",
36
+ name: "\u661F\u94FE",
37
37
  icon: "\u2728",
38
- description: "Classic particle linking effect",
38
+ description: "\u7ECF\u5178\u7C92\u5B50\u8FDE\u7EBF\u6548\u679C",
39
39
  backgroundGradient: "linear-gradient(180deg, #0f172a 0%, #1e293b 50%, #334155 100%)",
40
40
  options: (isDark) => {
41
41
  const colors = DEFAULT_COLORS;
@@ -49,7 +49,8 @@ var starlineTheme = {
49
49
  resize: { enable: true }
50
50
  },
51
51
  modes: {
52
- push: { quantity: 6 },
52
+ // 快速点击会触发 push 不断增加粒子和连线,限制触发强度和最大粒子数量可避免性能问题
53
+ push: { quantity: 2 },
53
54
  grab: {
54
55
  distance: 200,
55
56
  links: { opacity: 1, color: colors }
@@ -75,7 +76,9 @@ var starlineTheme = {
75
76
  },
76
77
  number: {
77
78
  density: { enable: true, width: 1920, height: 1080 },
78
- value: 100
79
+ value: 100,
80
+ // 限制粒子总量,防止快速点击后粒子与连线无限增长
81
+ limit: { value: 130, mode: "delete" }
79
82
  },
80
83
  opacity: { value: 0.7 },
81
84
  shape: { type: "circle" },
@@ -94,9 +97,9 @@ var starlineTheme = {
94
97
  // src/themes/snow.ts
95
98
  var snowTheme = {
96
99
  id: "snow",
97
- name: "Snowfall",
100
+ name: "\u98D8\u96EA",
98
101
  icon: "\u2744\uFE0F",
99
- description: "Romantic falling snowflakes",
102
+ description: "\u6D6A\u6F2B\u98D8\u843D\u96EA\u82B1",
100
103
  backgroundGradient: "linear-gradient(180deg, #1e3a5f 0%, #2d4a6b 50%, #3d5a7b 100%)",
101
104
  options: (isDark) => ({
102
105
  ...baseConfig,
@@ -148,9 +151,9 @@ var snowTheme = {
148
151
  // src/themes/bubble.ts
149
152
  var bubbleTheme = {
150
153
  id: "bubble",
151
- name: "Bubbles",
154
+ name: "\u6C14\u6CE1",
152
155
  icon: "\u{1FAE7}",
153
- description: "Dreamy rising bubbles",
156
+ description: "\u68A6\u5E7B\u4E0A\u5347\u6C14\u6CE1",
154
157
  backgroundGradient: "linear-gradient(180deg, #0a2647 0%, #144272 50%, #205295 100%)",
155
158
  options: (isDark) => ({
156
159
  ...baseConfig,
@@ -207,9 +210,9 @@ var bubbleTheme = {
207
210
  // src/themes/stars.ts
208
211
  var starsTheme = {
209
212
  id: "stars",
210
- name: "Twinkling Stars",
213
+ name: "\u7E41\u661F",
211
214
  icon: "\u2B50",
212
- description: "Sparkling starry sky",
215
+ description: "\u95EA\u70C1\u661F\u7A7A\u6548\u679C",
213
216
  backgroundGradient: "linear-gradient(180deg, #000000 0%, #1a1a2e 50%, #16213e 100%)",
214
217
  options: (isDark) => ({
215
218
  ...baseConfig,
@@ -221,7 +224,8 @@ var starsTheme = {
221
224
  resize: { enable: true }
222
225
  },
223
226
  modes: {
224
- push: { quantity: 3 },
227
+ // 限制快速点击触发的粒子 push 强度,避免连线过多造成卡顿
228
+ push: { quantity: 1 },
225
229
  connect: { distance: 100, links: { opacity: 0.3 }, radius: 150 }
226
230
  }
227
231
  },
@@ -239,7 +243,9 @@ var starsTheme = {
239
243
  },
240
244
  number: {
241
245
  density: { enable: true, width: 1920, height: 1080 },
242
- value: 120
246
+ value: 120,
247
+ // 限制粒子总量,避免快速点击后连线无限累积
248
+ limit: { value: 150, mode: "delete" }
243
249
  },
244
250
  opacity: {
245
251
  value: { min: 0.2, max: 1 },
@@ -274,9 +280,9 @@ var starsTheme = {
274
280
  // src/themes/firefly.ts
275
281
  var fireflyTheme = {
276
282
  id: "firefly",
277
- name: "Fireflies",
283
+ name: "\u8424\u706B\u866B",
278
284
  icon: "\u{1FAB2}",
279
- description: "Warm glowing firefly effect",
285
+ description: "\u6E29\u6696\u7684\u8424\u706B\u866B\u5149\u6548",
280
286
  backgroundGradient: "linear-gradient(180deg, #1a1a1a 0%, #2d2d2d 50%, #1a1a1a 100%)",
281
287
  options: (isDark) => ({
282
288
  ...baseConfig,
@@ -335,9 +341,9 @@ var fireflyTheme = {
335
341
  // src/themes/geometry.ts
336
342
  var geometryTheme = {
337
343
  id: "geometry",
338
- name: "Geometry",
344
+ name: "\u51E0\u4F55",
339
345
  icon: "\u{1F537}",
340
- description: "Floating abstract geometric shapes",
346
+ description: "\u6F02\u6D6E\u7684\u62BD\u8C61\u51E0\u4F55\u56FE\u5F62",
341
347
  backgroundGradient: "linear-gradient(180deg, #0f0c29 0%, #302b63 50%, #24243e 100%)",
342
348
  options: (isDark) => ({
343
349
  ...baseConfig,
@@ -349,7 +355,8 @@ var geometryTheme = {
349
355
  resize: { enable: true }
350
356
  },
351
357
  modes: {
352
- push: { quantity: 2 },
358
+ // 快速点击会持续触发 push,限制强度有助于降低连线/粒子带来的开销
359
+ push: { quantity: 1 },
353
360
  repulse: { distance: 150, duration: 0.4 }
354
361
  }
355
362
  },
@@ -367,7 +374,9 @@ var geometryTheme = {
367
374
  },
368
375
  number: {
369
376
  density: { enable: true, width: 1920, height: 1080 },
370
- value: 30
377
+ value: 30,
378
+ // 限制粒子总量,避免连续点击时粒子无限增加
379
+ limit: { value: 60, mode: "delete" }
371
380
  },
372
381
  opacity: {
373
382
  value: { min: 0.3, max: 0.7 }
@@ -401,9 +410,9 @@ var geometryTheme = {
401
410
  // src/themes/wave.ts
402
411
  var waveTheme = {
403
412
  id: "wave",
404
- name: "Particle Ocean",
413
+ name: "\u7C92\u5B50\u6D77\u6D0B",
405
414
  icon: "\u{1F30A}",
406
- description: "3D particle wave effect (requires three.js)",
415
+ description: "3D \u7C92\u5B50\u6CE2\u6D6A\u6548\u679C\uFF08\u9700\u8981 three.js\uFF09",
407
416
  isThreeJS: true,
408
417
  backgroundGradient: "linear-gradient(180deg, #000000 0%, #0a1628 50%, #0d1f3c 100%)",
409
418
  options: () => ({
@@ -480,7 +489,7 @@ var ParticleWave = ({
480
489
  })();
481
490
  } catch (e) {
482
491
  hasThree.current = false;
483
- console.warn('[react-particle-backgrounds] "three" is not installed. The wave theme requires it as a peer dependency.');
492
+ console.warn('[react-particle-backgrounds] \u672A\u5B89\u88C5 "three"\u3002\u6CE2\u6D6A\u4E3B\u9898\u9700\u8981\u5B83\u4F5C\u4E3A peer dependency\u3002');
484
493
  return;
485
494
  }
486
495
  if (!containerRef.current) return;
@@ -815,6 +824,7 @@ var ParticleWave = ({
815
824
  );
816
825
  };
817
826
  var ParticleWave_default = ParticleWave;
827
+ var instanceCounter = 0;
818
828
  var ParticlesBackground = ({
819
829
  theme: themeProp,
820
830
  isDark: isDarkProp,
@@ -824,6 +834,9 @@ var ParticlesBackground = ({
824
834
  }) => {
825
835
  var _a, _b;
826
836
  const [init, setInit] = useState(false);
837
+ const [instanceId, setInstanceId] = useState(() => ++instanceCounter);
838
+ const containerRef = useRef(void 0);
839
+ const isFirstMount = useRef(true);
827
840
  const ctx = useParticleThemeOptional();
828
841
  const themeId = (_a = themeProp != null ? themeProp : ctx == null ? void 0 : ctx.themeId) != null ? _a : DEFAULT_THEME_ID;
829
842
  const isDark = (_b = isDarkProp != null ? isDarkProp : ctx == null ? void 0 : ctx.isDark) != null ? _b : true;
@@ -837,6 +850,25 @@ var ParticlesBackground = ({
837
850
  setInit(true);
838
851
  });
839
852
  }, []);
853
+ useEffect(() => {
854
+ if (!isFirstMount.current) {
855
+ setInstanceId(++instanceCounter);
856
+ }
857
+ isFirstMount.current = false;
858
+ return () => {
859
+ if (containerRef.current) {
860
+ containerRef.current.destroy();
861
+ containerRef.current = void 0;
862
+ }
863
+ };
864
+ }, [themeId, isDark]);
865
+ const particlesLoaded = useCallback(async (container) => {
866
+ if (containerRef.current && containerRef.current !== container) {
867
+ containerRef.current.destroy();
868
+ }
869
+ containerRef.current = container;
870
+ onLoaded == null ? void 0 : onLoaded(container);
871
+ }, [onLoaded]);
840
872
  const options = useMemo(() => theme.options(isDark), [theme, isDark]);
841
873
  if (themeId === "none") return null;
842
874
  if (theme.isThreeJS) {
@@ -850,16 +882,17 @@ var ParticlesBackground = ({
850
882
  );
851
883
  }
852
884
  if (!init) return null;
885
+ const particlesId = `rpb-tsparticles-${instanceId}`;
853
886
  return /* @__PURE__ */ jsx(
854
887
  Particles,
855
888
  {
856
- id: "rpb-tsparticles",
889
+ id: particlesId,
857
890
  className,
858
891
  style,
859
- particlesLoaded: async (container) => onLoaded == null ? void 0 : onLoaded(container),
892
+ particlesLoaded,
860
893
  options
861
894
  },
862
- themeId
895
+ particlesId
863
896
  );
864
897
  };
865
898
  var ParticlesBackground_default = ParticlesBackground;
@@ -882,7 +915,7 @@ var ThemeSelector = ({
882
915
  "button",
883
916
  {
884
917
  onClick: () => setOpen(true),
885
- title: "Theme Settings",
918
+ title: "\u4E3B\u9898\u8BBE\u7F6E",
886
919
  style: {
887
920
  position: "fixed",
888
921
  ...positionStyles[position],
@@ -955,7 +988,7 @@ var ThemeSelector = ({
955
988
  borderBottom: "1px solid #f0f0f0"
956
989
  },
957
990
  children: [
958
- /* @__PURE__ */ jsx("span", { style: { fontWeight: 600, fontSize: 16 }, children: "Particle Theme" }),
991
+ /* @__PURE__ */ jsx("span", { style: { fontWeight: 600, fontSize: 16 }, children: "\u7C92\u5B50\u4E3B\u9898" }),
959
992
  /* @__PURE__ */ jsx(
960
993
  "button",
961
994
  {
@@ -976,9 +1009,9 @@ var ThemeSelector = ({
976
1009
  ),
977
1010
  /* @__PURE__ */ jsx("div", { style: { padding: 16, display: "flex", flexDirection: "column", gap: 12 }, children: [...particleThemes, {
978
1011
  id: "none",
979
- name: "None",
1012
+ name: "\u65E0",
980
1013
  icon: "\u{1F6AB}",
981
- description: "Disable particle effects"
1014
+ description: "\u5173\u95ED\u7C92\u5B50\u6548\u679C"
982
1015
  }].map((theme) => {
983
1016
  const isActive = theme.id === themeId;
984
1017
  return /* @__PURE__ */ jsxs(
@@ -1066,7 +1099,7 @@ var ThemeSelector = ({
1066
1099
  color: "#6b7280",
1067
1100
  lineHeight: 1.6
1068
1101
  },
1069
- children: "Your theme selection is automatically saved and will be remembered on your next visit."
1102
+ children: "\u4F60\u7684\u4E3B\u9898\u9009\u62E9\u4F1A\u81EA\u52A8\u4FDD\u5B58\uFF0C\u4E0B\u6B21\u8BBF\u95EE\u65F6\u5C06\u81EA\u52A8\u6062\u590D\u3002"
1070
1103
  }
1071
1104
  ) })
1072
1105
  ]