You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何无突兀刷新修改tsParticles配置?Next.js+TypeScript场景

如何在tsParticles中无突兀修改粒子配置参数

在TypeScript+Next.js项目中使用tsParticles组件时,想通过按钮点击程序化修改粒子速度、颜色等配置,但将speed设为状态变量并加入useMemo依赖的方式,会导致粒子系统突兀刷新。以下是实现无突兀配置修改的方案:

核心思路

不要通过更新options对象触发组件重新渲染(这会重启粒子系统),而是直接获取tsParticles的容器实例,在现有粒子系统上动态修改参数,实现平滑过渡。

具体实现步骤

  1. 保存粒子容器实例:使用useRef存储tsParticles的Container实例,在particlesLoaded回调中完成赋值。
  2. 定义可修改的状态变量:比如粒子速度、颜色等需要动态调整的参数。
  3. 编写动态修改函数:通过容器实例直接修改粒子配置,无需更新整个options对象。

修改后的完整组件代码

"use client"

import { Container, ISourceOptions, MoveDirection, OutMode } from "@tsparticles/engine";
import Particles, { initParticlesEngine } from "@tsparticles/react";
import { loadSlim } from "@tsparticles/slim";

import React, { useEffect, useMemo, useState, useRef } from "react";

const ParticlesComponent: React.FC = ({}) => {
  const [init, setInit] = useState(false);
  // 保存粒子容器实例
  const particlesContainerRef = useRef<Container | null>(null);
  // 定义可修改的状态变量
  const [speed, setSpeed] = useState(0.1);
  const [particleColor, setParticleColor] = useState("#ffffff");

  useEffect(() => {
    initParticlesEngine(async (engine) => {
      await loadSlim(engine);
    }).then(() => {
      setInit(true);
    });
  }, []);

  const particlesLoaded = async (container?: Container): Promise<void> => {
    // 赋值容器实例
    if (container) {
      particlesContainerRef.current = container;
    }
  };

  // 动态修改速度的函数
  const handleSpeedChange = (newSpeed: number) => {
    setSpeed(newSpeed);
    if (particlesContainerRef.current) {
      // 直接修改容器内粒子的移动速度
      particlesContainerRef.current.options.particles.move.speed = newSpeed;
      // 通知粒子系统更新配置
      particlesContainerRef.current.refresh();
    }
  };

  // 动态修改颜色的函数
  const handleColorChange = (newColor: string) => {
    setParticleColor(newColor);
    if (particlesContainerRef.current) {
      // 直接修改粒子颜色配置
      particlesContainerRef.current.options.particles.color.value = [newColor];
      // 遍历现有粒子,即时更新颜色
      particlesContainerRef.current.particles.forEach(particle => {
        particle.color.value = newColor;
      });
    }
  };

  const options: ISourceOptions = useMemo(
    () => ({
      background: {
        color: {
          value: "#0F0F11",
        },
      },
      fpsLimit: 60,
      particles: {
        color: {
          value: [particleColor],
        },
        move: {
          direction: MoveDirection.none,
          enable: true,
          outModes: {
            default: OutMode.out,
          },
          random: false,
          speed: speed,
          straight: false,
        },
        number: {
          density: {
            enable: true,
          },
          value: 1800,
        },
        opacity: {
          value: { min: 0.1, max: 0.5 },
        },
        shape: {
          type: "circle",
        },
        size: {
          value: { min: 0.1, max: 1 },
        },
      },
    }),
    [], // 这里不再依赖状态变量,避免触发组件重新初始化
  );

  return (
    <>
      <div className="fixed top-4 left-4 z-10">
        <button
          onClick={() => handleSpeedChange(0.5)}
          className="mr-2 px-4 py-2 bg-blue-500 text-white rounded"
        >
          加快速度
        </button>
        <button
          onClick={() => handleSpeedChange(0.1)}
          className="mr-2 px-4 py-2 bg-blue-500 text-white rounded"
        >
          减慢速度
        </button>
        <button
          onClick={() => handleColorChange("#ff0000")}
          className="px-4 py-2 bg-red-500 text-white rounded"
        >
          变红
        </button>
      </div>
      <Particles options={options} particlesLoaded={particlesLoaded} className="-z-20 absolute"></Particles>
    </>
  );
};

export default ParticlesComponent;

关键说明

  • 容器实例操作:通过particlesContainerRef.current直接访问粒子系统的配置和粒子实例,修改后调用refresh()让全局配置生效;针对颜色这类需要即时更新的属性,直接遍历粒子修改单个实例的属性。
  • 避免options依赖状态:useMemo的依赖数组保持为空,防止状态变化时重新生成options导致粒子系统重启,彻底解决突兀刷新问题。

内容的提问来源于stack exchange,提问作者Riccardo Perego

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 01:27:03