使用React和TsParticles建立令人驚歎的粒子動畫

使用React和TsParticles建立令人驚歎的粒子動畫

React TsParticles 是一個流行的開源庫,能讓您輕鬆地將粒子動畫整合到 React 應用程式中。它構建於 TsParticles 庫之上,後者提供了一種靈活、可定製的方式來建立各種粒子效果和動畫。React TsParticles 簡化了將這些粒子動畫整合到 React 專案中的過程,使其成為為網站或網路應用程式新增動態和視覺吸引力元素的強大工具,本文將向您展示幾個使用示例。

在 Web 專案中新增粒子動畫可以增強整體使用者體驗,使網站或 Web 應用程式更具吸引力和視覺吸引力。以下是將粒子動畫融入網頁專案的一些主要優勢:

  • 視覺吸引力:粒子動畫可以通過新增動態和吸引眼球的元素,使網站更具視覺吸引力。它們可以創造出一種深度感和互動性,使你的網站在競爭中脫穎而出。
  • 使用者參與:動畫能吸引使用者的注意力,並能讓使用者參與到您的內容中來。互動顆粒可以鼓勵使用者與網站互動,探索網站功能。
  • 使用者互動:互動式粒子動畫可以響應使用者的操作,如滑鼠移動或觸控,從而使網站更具響應性和互動性。這可以改善整體使用者體驗。
  • 背景效果:粒子動畫通常用於背景效果,為內容提供有吸引力的背景。這對登陸頁面、作品集和其他視覺導向型網站都很有效。

安裝和設定 React TsParticles

在您的 React 應用程式專案目錄下,您可以使用以下 bash 指令碼通過您喜歡的軟體包安裝程式安裝 TsParticles 依賴項:

對於 npm:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
npm install react-tsparticles tsparticles
npm install react-tsparticles tsparticles
npm install react-tsparticles tsparticles

對於 yarn:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
yarn add react-tsparticles tsparticles
yarn add react-tsparticles tsparticles
yarn add react-tsparticles tsparticles

使用 TsParticles 建立動畫

在本節中,我們將討論 TsParticles 提供的各種動畫,以及如何將它們整合到網路應用中。

彩紙效果

在第一個動畫中,我們將使用 TsParticles 在網路應用程式中生成紙屑。紙屑是一種五顏六色的小塊材料,通常在特殊的慶祝場合投擲。在網路應用程式中,當使用者完成一項任務時,例如在電子學習網站上完成一門課程,可以用它來描繪一種慶祝形式。

要建立該動畫,請按照以下步驟進行:

  • 首先,在 src/App.js 目錄中,我們將清除 boiler 模板程式碼並匯入必要的 TsParticle 依賴項:
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import Particles from "react-tsparticles";
import { loadFull } from "tsparticles";
import { useCallback } from "react";
import Particles from "react-tsparticles"; import { loadFull } from "tsparticles"; import { useCallback } from "react";
import Particles from "react-tsparticles";
import { loadFull } from "tsparticles";
import { useCallback } from "react";
  • 接下來,我們將定義動畫配置和初始化 TsParticles 動畫的函式:
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
//...
function App() {
const config = {
//Here we define the animation type, properties and behavior
};
const particlesInit = useCallback(async (engine) => {
// here we initialize the particles animation
await loadFull(engine);
}, []);
//... function App() { const config = { //Here we define the animation type, properties and behavior }; const particlesInit = useCallback(async (engine) => { // here we initialize the particles animation await loadFull(engine); }, []);
//...
function App() {
const config = {
//Here we define the animation type, properties and behavior 
};
const particlesInit = useCallback(async (engine) => {
// here we initialize the particles animation
await loadFull(engine);
}, []);

我們將使用 useCallback 來記憶 particleInit 函式,因此由於依賴關係陣列為空 [],React 不會在每次呈現時建立新函式,而只會在元件掛載時的第一次呈現時建立。

App.js 元件的 return 塊中,我們可以使用 config 和初始化函式訪問動畫:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
//...
return (
<div className="App">
<Particles options={config} init={particlesInit} />
</div>
);
export default App;
//... return ( <div className="App"> <Particles options={config} init={particlesInit} /> </div> ); export default App;
//...
return (
<div className="App">
<Particles options={config} init={particlesInit} />
</div>
);
export default App;

對於彩紙動畫,我們將在 config 中定義以下屬性:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const config = {
fullScreen: {
zIndex: 1,
},
background: {
color: "#000",
},
emitters: {
position: {
x: 50,
y: 100,
},
rate: {
quantity: 5,
delay: 0.15,
},
},
particles: {
color: {
value: ["#1E00FF", "#FF0061", "#E1FF00", "#00FF9E"],
},
move: {
decay: 0.05,
direction: "top",
enable: true,
gravity: {
enable: true,
},
outModes: {
top: "none",
default: "destroy",
},
speed: {
min: 50,
max: 100,
},
},
number: {
value: 0,
},
opacity: {
value: 1,
},
rotate: {
value: {
min: 0,
max: 360,
},
direction: "random",
animation: {
enable: true,
speed: 30,
},
},
tilt: {
direction: "random",
enable: true,
value: {
min: 0,
max: 360,
},
animation: {
enable: true,
speed: 30,
},
},
size: {
value: 10,
animation: {
enable: true,
startValue: "min",
count: 1,
speed: 16,
sync: true,
},
},
shape: {
type: ["circle", "square"],
options: {},
},
},
};
const config = { fullScreen: { zIndex: 1, }, background: { color: "#000", }, emitters: { position: { x: 50, y: 100, }, rate: { quantity: 5, delay: 0.15, }, }, particles: { color: { value: ["#1E00FF", "#FF0061", "#E1FF00", "#00FF9E"], }, move: { decay: 0.05, direction: "top", enable: true, gravity: { enable: true, }, outModes: { top: "none", default: "destroy", }, speed: { min: 50, max: 100, }, }, number: { value: 0, }, opacity: { value: 1, }, rotate: { value: { min: 0, max: 360, }, direction: "random", animation: { enable: true, speed: 30, }, }, tilt: { direction: "random", enable: true, value: { min: 0, max: 360, }, animation: { enable: true, speed: 30, }, }, size: { value: 10, animation: { enable: true, startValue: "min", count: 1, speed: 16, sync: true, }, }, shape: { type: ["circle", "square"], options: {}, }, }, };
const config = {
fullScreen: {
zIndex: 1,
},
background: {
color: "#000",
},
emitters: {
position: {
x: 50,
y: 100,
},
rate: {
quantity: 5,
delay: 0.15,
},
},
particles: {
color: {
value: ["#1E00FF", "#FF0061", "#E1FF00", "#00FF9E"],
},
move: {
decay: 0.05,
direction: "top",
enable: true,
gravity: {
enable: true,
},
outModes: {
top: "none",
default: "destroy",
},
speed: {
min: 50,
max: 100,
},
},
number: {
value: 0,
},
opacity: {
value: 1,
},
rotate: {
value: {
min: 0,
max: 360,
},
direction: "random",
animation: {
enable: true,
speed: 30,
},
},
tilt: {
direction: "random",
enable: true,
value: {
min: 0,
max: 360,
},
animation: {
enable: true,
speed: 30,
},
},
size: {
value: 10,
animation: {
enable: true,
startValue: "min",
count: 1,
speed: 16,
sync: true,
},
},
shape: {
type: ["circle", "square"],
options: {},
},
},
};

我們可以定義上述每個屬性的功能:

  • Fullscreen:在該屬性中,我們使用 z-index 屬性將預期動畫的堆疊順序設為 “1”。
  • Emitters:在這裡,我們使用 position 屬性指定了粒子動畫的初始 X 和 Y 原點。我們還使用 rate 指定了每次發射的數量以及每次建立粒子之間的延遲。
  • Particles:通過該屬性,我們定義了發射粒子的質量和行為。
    • Color:如上圖所示,可以是單一顏色,也可以是不同顏色的集合。這將為動畫中建立的每個粒子設定顏色。
    • Move:該屬性定義:
      • 粒子動畫的 direction
        使用 decay 屬性指定粒子開始失去速度的時間。
        我們還將 gravity 屬性設定為 true,以啟用重力對粒子的影響。
    • Number:這是動畫中粒子的初始數量。

opacityrotatetiltsize, 和 shape 均執行其名稱所暗示的功能。要執行應用程式,請在工作目錄的終端環境中使用 npm start 命令,然後在瀏覽器中開啟結果。您將看到與下面 GIF 類似的頁面:

彩紙動畫

通過修改 config 屬性,我們可以在 TsParticles 中建立獨特的動畫形式。例如,我們可以用下面的程式碼獲得紙屑彈出動畫:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const config = {
fullScreen: {
zIndex: 1,
},
background: {
color: "#000",
},
emitters: {
life: {
count: 0,
duration: 0.1,
delay: 0.4,
},
rate: {
delay: 0.1,
quantity: 150,
},
size: {
width: 0,
height: 0,
},
},
particles: {
color: {
value: ["#1E00FF", "#FF0061", "#E1FF00", "#00FF9E"],
},
move: {
enable: true,
gravity: {
enable: true,
acceleration: 10,
},
speed: {
min: 10,
max: 20,
},
decay: 0.1,
direction: "none",
straight: false,
outModes: {
default: "destroy",
top: "none",
},
},
number: {
value: 0,
},
opacity: {
value: 1,
animation: {
enable: true,
minimumValue: 0,
speed: 2,
startValue: "max",
destroy: "min",
},
},
rotate: {
value: {
min: 0,
max: 360,
},
direction: "random",
animation: {
enable: true,
speed: 30,
},
},
tilt: {
direction: "random",
enable: true,
value: {
min: 0,
max: 360,
},
animation: {
enable: true,
speed: 30,
},
},
size: {
value: 10,
random: {
enable: true,
minimumValue: 2,
},
},
shape: {
type: ["circle", "square"],
options: {},
},
},
};
const config = { fullScreen: { zIndex: 1, }, background: { color: "#000", }, emitters: { life: { count: 0, duration: 0.1, delay: 0.4, }, rate: { delay: 0.1, quantity: 150, }, size: { width: 0, height: 0, }, }, particles: { color: { value: ["#1E00FF", "#FF0061", "#E1FF00", "#00FF9E"], }, move: { enable: true, gravity: { enable: true, acceleration: 10, }, speed: { min: 10, max: 20, }, decay: 0.1, direction: "none", straight: false, outModes: { default: "destroy", top: "none", }, }, number: { value: 0, }, opacity: { value: 1, animation: { enable: true, minimumValue: 0, speed: 2, startValue: "max", destroy: "min", }, }, rotate: { value: { min: 0, max: 360, }, direction: "random", animation: { enable: true, speed: 30, }, }, tilt: { direction: "random", enable: true, value: { min: 0, max: 360, }, animation: { enable: true, speed: 30, }, }, size: { value: 10, random: { enable: true, minimumValue: 2, }, }, shape: { type: ["circle", "square"], options: {}, }, }, };
const config = {
fullScreen: {
zIndex: 1,
},
background: {
color: "#000",
},
emitters: {
life: {
count: 0,
duration: 0.1,
delay: 0.4,
},
rate: {
delay: 0.1,
quantity: 150,
},
size: {
width: 0,
height: 0,
},
},
particles: {
color: {
value: ["#1E00FF", "#FF0061", "#E1FF00", "#00FF9E"],
},
move: {
enable: true,
gravity: {
enable: true,
acceleration: 10,
},
speed: {
min: 10,
max: 20,
},
decay: 0.1,
direction: "none",
straight: false,
outModes: {
default: "destroy",
top: "none",
},
},
number: {
value: 0,
},
opacity: {
value: 1,
animation: {
enable: true,
minimumValue: 0,
speed: 2,
startValue: "max",
destroy: "min",
},
},
rotate: {
value: {
min: 0,
max: 360,
},
direction: "random",
animation: {
enable: true,
speed: 30,
},
},
tilt: {
direction: "random",
enable: true,
value: {
min: 0,
max: 360,
},
animation: {
enable: true,
speed: 30,
},
},
size: {
value: 10,
random: {
enable: true,
minimumValue: 2,
},
},
shape: {
type: ["circle", "square"],
options: {},
},
},
};

執行應用程式將產生以下結果:

紙屑彈出動畫

煙花效果

在本節中,我們將使用 TsParticles 按以下步驟建立煙花效果:

  • 首先,我們將設定黑色背景和全屏屬性,以便煙花清晰可見。此外,我們還將定義  fpsLimit(幀速率限制),使動畫效果更佳,不會出現不流暢的情況,並將 detectRetina 值設為 “true”,以改善粒子外觀:
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const config = {
fullScreen: {
enable: true,
},
detectRetina: true,
background: {
color: "#000",
},
fpsLimit: 60,
};
const config = { fullScreen: { enable: true, }, detectRetina: true, background: { color: "#000", }, fpsLimit: 60, };
const config = {
fullScreen: {
enable: true,
},
detectRetina: true,
background: {
color: "#000",
},
fpsLimit: 60,
};
  • 接下來,我們將定義粒子的發射器屬性。為了模模擬實的煙花,我們需要在建立爆炸效果之前,將粒子向上移動到不同的 x 座標和 y 座標上:
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
//...
emitters: {
direction: "top",
position: {
y: 100,
x: 50,
},
rate: {
delay: 0.03,
quantity: 1,
},
life: {
count: 0,
duration: 0.1,
delay: 0.1,
},
size: {
width: 80,
height: 0,
},
//...
//... emitters: { direction: "top", position: { y: 100, x: 50, }, rate: { delay: 0.03, quantity: 1, }, life: { count: 0, duration: 0.1, delay: 0.1, }, size: { width: 80, height: 0, }, //...
//...
emitters: {
direction: "top",
position: {
y: 100,
x: 50,
},
rate: {
delay: 0.03,
quantity: 1,
},
life: {
count: 0,
duration: 0.1,
delay: 0.1,
},
size: {
width: 80,
height: 0,
},
//...

我們還定義了粒子的 ratelife, 和 size 屬性。接下來,我們將建立粒子並製作動畫:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// still within the emitters property
particles: {
number: {
value: 0,
},
destroy: {
mode: "split", // using splits we will achieve a firework effect
split: {
rate: {
value: 100, //number of splits to be created
},
particles: {
// Splitted practicle properties
color: {
//color of particles after explosion
value: [
"#FF0000" /*Red */,
"#0000FF" /*blue */,
"#FFFF00" /*yellow*/,
],
},
opacity: {
value: 1,
animation: {
enable: true,
speed: 0.2,
minimumValue: 0.1,
sync: false,
startValue: "max", // create multiple fireworks
destroy: "min",
},
},
shape: {
// pattern of the explosion
type: "star",
},
size: {
value: 3,
animation: {
enable: false,
},
},
life: {
count: 1, //amount of time
duration: {
value: {
min: 1,
max: 2,
},
},
},
move: {
enable: true,
gravity: {
enable: false,
},
speed: 3,
direction: "none",
outMode: "destroy",
},
},
},
},
life: {
count: 1,
},
shape: {
type: "line",
},
size: {
value: { min: 1, max: 100 },
animation: {
enable: true,
sync: true,
speed: 150,
startValue: "random",
destroy: "min",
},
},
stroke: {
color: {
// color of the fireworks stroke
value: ["#00FFFF", "#FF8000", "#0080FF"],
},
width: 1,
},
rotate: {
path: true,
},
move: {
enable: true,
gravity: {
acceleration: 15,
enable: true,
inverse: true,
maxSpeed: 100,
},
speed: { min: 10, max: 20 },
outModes: {
default: "destroy",
},
trail: {
// trail for split particles
enable: true,
length: 10,
},
},
},
// still within the emitters property particles: { number: { value: 0, }, destroy: { mode: "split", // using splits we will achieve a firework effect split: { rate: { value: 100, //number of splits to be created }, particles: { // Splitted practicle properties color: { //color of particles after explosion value: [ "#FF0000" /*Red */, "#0000FF" /*blue */, "#FFFF00" /*yellow*/, ], }, opacity: { value: 1, animation: { enable: true, speed: 0.2, minimumValue: 0.1, sync: false, startValue: "max", // create multiple fireworks destroy: "min", }, }, shape: { // pattern of the explosion type: "star", }, size: { value: 3, animation: { enable: false, }, }, life: { count: 1, //amount of time duration: { value: { min: 1, max: 2, }, }, }, move: { enable: true, gravity: { enable: false, }, speed: 3, direction: "none", outMode: "destroy", }, }, }, }, life: { count: 1, }, shape: { type: "line", }, size: { value: { min: 1, max: 100 }, animation: { enable: true, sync: true, speed: 150, startValue: "random", destroy: "min", }, }, stroke: { color: { // color of the fireworks stroke value: ["#00FFFF", "#FF8000", "#0080FF"], }, width: 1, }, rotate: { path: true, }, move: { enable: true, gravity: { acceleration: 15, enable: true, inverse: true, maxSpeed: 100, }, speed: { min: 10, max: 20 }, outModes: { default: "destroy", }, trail: { // trail for split particles enable: true, length: 10, }, }, },
// still within the emitters property
particles: {
number: {
value: 0,
},
destroy: {
mode: "split", // using splits we will achieve a firework effect
split: {
rate: {
value: 100, //number of splits to be created
},
particles: {
// Splitted practicle properties
color: {
//color of particles after explosion
value: [
"#FF0000" /*Red */,
"#0000FF" /*blue */,
"#FFFF00" /*yellow*/,
],
},
opacity: {
value: 1,
animation: {
enable: true,
speed: 0.2,
minimumValue: 0.1,
sync: false,
startValue: "max", // create multiple fireworks
destroy: "min",
},
},
shape: {
// pattern of the explosion
type: "star",
},
size: {
value: 3,
animation: {
enable: false,
},
},
life: {
count: 1, //amount of time
duration: {
value: {
min: 1,
max: 2,
},
},
},
move: {
enable: true, 
gravity: {
enable: false, 
},
speed: 3, 
direction: "none", 
outMode: "destroy",
},
},
},
},
life: {
count: 1,
},
shape: {
type: "line",
},
size: {
value: { min: 1, max: 100 },
animation: {
enable: true,
sync: true,
speed: 150,
startValue: "random",
destroy: "min",
},
},
stroke: {
color: {
// color of the fireworks stroke
value: ["#00FFFF", "#FF8000", "#0080FF"],
},
width: 1,
},
rotate: {
path: true, 
},
move: {
enable: true,
gravity: {
acceleration: 15,
enable: true,
inverse: true,
maxSpeed: 100,
},
speed: { min: 10, max: 20 },
outModes: {
default: "destroy",
},
trail: {
// trail for split particles
enable: true,
length: 10,
},
},
},

執行應用程式將得到以下效果:

煙花效果

使用預設

雖然建立粒子配置為控制動畫屬性提供了更大的靈活性,但也需要一定的時間才能完成。為了快速提供粒子動畫,TsParticles 引入了預設粒子的使用。預設允許使用者匯入並使用預先配置好的粒子動畫。例如,我們可以使用 TsParticles 提供的煙花預設,如下圖所示。

首先,我們在 CLI 中使用以下命令安裝預設:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
npm install tsparticles-preset-fireworks
npm install tsparticles-preset-fireworks
npm install tsparticles-preset-fireworks

然後,我們就可以匯入並使用它,如下所示:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import Particles from "react-tsparticles";
import { loadFull } from "tsparticles";
import { useCallback } from "react";
import { loadFireworksPreset } from "tsparticles-preset-fireworks";
const fireworkInit = useCallback(async (engine) => {
await loadFireworksPreset(engine);
}, []);
const options = {
preset: "fireworks",
};
return (
<div className="App">
<Particles options={options} init={fireworkInit} />
</div>
);
}
import Particles from "react-tsparticles"; import { loadFull } from "tsparticles"; import { useCallback } from "react"; import { loadFireworksPreset } from "tsparticles-preset-fireworks"; const fireworkInit = useCallback(async (engine) => { await loadFireworksPreset(engine); }, []); const options = { preset: "fireworks", }; return ( <div className="App"> <Particles options={options} init={fireworkInit} /> </div> ); }
import Particles from "react-tsparticles";
import { loadFull } from "tsparticles";
import { useCallback } from "react";
import { loadFireworksPreset } from "tsparticles-preset-fireworks";  
const fireworkInit = useCallback(async (engine) => {
await loadFireworksPreset(engine);
}, []);
const options = {
preset: "fireworks",
};
return (
<div className="App">
<Particles options={options} init={fireworkInit} />
</div>
);
}

最終效果:

TsParticles 提供的煙花預設

利用粒子實現互動

在本節中,我們將學習如何根據使用者互動(如點選和懸停事件)生成 TsParticle 動畫。如下程式碼所示,滑鼠點選事件可觸發粒子 emitter 動作:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
background: {
color: "#000",
},
interactivity: {
events: {
onClick: {
enable: true,
mode: "emitter",
},
},
// emitter and mode here
},
background: { color: "#000", }, interactivity: { events: { onClick: { enable: true, mode: "emitter", }, }, // emitter and mode here },
background: {
color: "#000",
},
interactivity: {
events: {
onClick: {
enable: true,
mode: "emitter",
},
},
// emitter and mode here
},

接下來,我們定義一個包含 emitter 屬性的 mode,然後新增其餘的動畫屬性:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
//....
modes: {
emitters: {
direction: "top",
spawnColor: {
value: "#FF8000",
animation: {
h: {
enable: true,
offset: {
min: -1.4,
max: 1.4,
},
speed: 0.1,
sync: false,
},
l: {
enable: true,
offset: {
min: 20,
max: 80,
},
speed: 0,
sync: false,
},
},
},
life: {
count: 1,
duration: 0.1,
delay: 0.6,
},
rate: {
delay: 0.1,
quantity: 100,
},
size: {
width: 0,
height: 0,
},
},
},
//.... modes: { emitters: { direction: "top", spawnColor: { value: "#FF8000", animation: { h: { enable: true, offset: { min: -1.4, max: 1.4, }, speed: 0.1, sync: false, }, l: { enable: true, offset: { min: 20, max: 80, }, speed: 0, sync: false, }, }, }, life: { count: 1, duration: 0.1, delay: 0.6, }, rate: { delay: 0.1, quantity: 100, }, size: { width: 0, height: 0, }, }, },
//....
modes: {
emitters: {
direction: "top",
spawnColor: {
value: "#FF8000",
animation: {
h: {
enable: true,
offset: {
min: -1.4,
max: 1.4,
},
speed: 0.1,
sync: false,
},
l: {
enable: true,
offset: {
min: 20,
max: 80,
},
speed: 0,
sync: false,
},
},
},
life: {
count: 1,
duration: 0.1,
delay: 0.6,
},
rate: {
delay: 0.1,
quantity: 100,
},
size: {
width: 0,
height: 0,
},
},
},

最後,我們定義粒子的屬性:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
particles: {
number: {
value: 0,
},
color: {
value: "#0080FF",
},
shape: {
type: ["circle", "square", "triangle"],
},
opacity: {
value: { min: 0, max: 1 },
animation: {
enable: true,
speed: 1,
startValue: "max",
destroy: "min",
},
},
size: {
value: { min: 6, max: 12 },
},
life: {
duration: {
sync: true,
value: 7,
},
count: 1,
},
move: {
enable: true,
gravity: {
enable: true,
},
drift: {
min: -2,
max: 2,
},
speed: { min: 10, max: 30 },
decay: 0.1,
direction: "none",
random: false,
straight: false,
outModes: {
default: "destroy",
top: "none",
},
},
rotate: {
value: {
min: 0,
max: 360,
},
direction: "random",
move: true,
animation: {
enable: true,
speed: 60,
},
},
tilt: {
direction: "random",
enable: true,
move: true,
value: {
min: 0,
max: 360,
},
animation: {
enable: true,
speed: 60,
},
},
roll: {
darken: {
enable: true,
value: 25,
},
enable: true,
speed: {
min: 15,
max: 25,
},
},
wobble: {
distance: 30,
enable: true,
move: true,
speed: {
min: -15,
max: 15,
},
},
},
particles: { number: { value: 0, }, color: { value: "#0080FF", }, shape: { type: ["circle", "square", "triangle"], }, opacity: { value: { min: 0, max: 1 }, animation: { enable: true, speed: 1, startValue: "max", destroy: "min", }, }, size: { value: { min: 6, max: 12 }, }, life: { duration: { sync: true, value: 7, }, count: 1, }, move: { enable: true, gravity: { enable: true, }, drift: { min: -2, max: 2, }, speed: { min: 10, max: 30 }, decay: 0.1, direction: "none", random: false, straight: false, outModes: { default: "destroy", top: "none", }, }, rotate: { value: { min: 0, max: 360, }, direction: "random", move: true, animation: { enable: true, speed: 60, }, }, tilt: { direction: "random", enable: true, move: true, value: { min: 0, max: 360, }, animation: { enable: true, speed: 60, }, }, roll: { darken: { enable: true, value: 25, }, enable: true, speed: { min: 15, max: 25, }, }, wobble: { distance: 30, enable: true, move: true, speed: { min: -15, max: 15, }, }, },
particles: {
number: {
value: 0,
},
color: {
value: "#0080FF",
},
shape: {
type: ["circle", "square", "triangle"],
},
opacity: {
value: { min: 0, max: 1 },
animation: {
enable: true,
speed: 1,
startValue: "max",
destroy: "min",
},
},
size: {
value: { min: 6, max: 12 },
},
life: {
duration: {
sync: true,
value: 7,
},
count: 1,
},
move: {
enable: true,
gravity: {
enable: true,
},
drift: {
min: -2,
max: 2,
},
speed: { min: 10, max: 30 },
decay: 0.1,
direction: "none",
random: false,
straight: false,
outModes: {
default: "destroy",
top: "none",
},
},
rotate: {
value: {
min: 0,
max: 360,
},
direction: "random",
move: true,
animation: {
enable: true,
speed: 60,
},
},
tilt: {
direction: "random",
enable: true,
move: true,
value: {
min: 0,
max: 360,
},
animation: {
enable: true,
speed: 60,
},
},
roll: {
darken: {
enable: true,
value: 25,
},
enable: true,
speed: {
min: 15,
max: 25,
},
},
wobble: {
distance: 30,
enable: true,
move: true,
speed: {
min: -15,
max: 15,
},
},
},

在上面的程式碼中,我們建立了一個向上彈出的紙屑效果,其原點位於滑鼠點選的位置:

向上彈出的紙屑效果

以類似的模式,我們還可以定義懸停動畫,當滑鼠在螢幕上懸停時,動畫會發出微粒。為此,我們還將使用 interactivity 屬性:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
const config = {
background: {
color: "#000",
},
interactivity: {
detectsOn: "window",
events: {
onhover: {
enable: true,
mode: "trail"
},
//...
const config = { background: { color: "#000", }, interactivity: { detectsOn: "window", events: { onhover: { enable: true, mode: "trail" }, //...
const config = {
background: {
color: "#000",
},
interactivity: {
detectsOn: "window",
events: {
onhover: {
enable: true,
mode: "trail"
},
//...

在這裡,我們定義了檢測滑鼠事件的區域(即視窗)和要檢測的事件型別。我們將使用 onhover 效果建立滑鼠軌跡:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
//...
resize: true,
},
modes: {
grab: {
distance: 400,
line_linked: {
opacity: 1,
},
},
bubble: {
distance: 400,
size: 40,
duration: 2,
opacity: 0.8,
speed: 3,
},
repulse: {
distance: 200,
},
push: {
particles_nb: 4,
},
remove: {
particles_nb: 2,
},
trail: {
delay: 0.005,
quantity: 5,
pauseOnStop: true,
},
},
},
retina_detect: true,
fullScreen: {
enable: true,
zIndex: 100,
},
fpsLimit: 60,
particles: {
number: {
value: 0,
density: {
enable: true,
value_area: 800,
},
},
color: {
value: "#0080FF",
},
shape: {
type: ["circle", "square", "triangle"],
},
opacity: {
value: { min: 0, max: 1 },
animation: {
enable: true,
speed: 1,
startValue: "max",
destroy: "min",
},
},
size: {
value: { min: 6, max: 12 },
},
links: {
enable: false,
},
move: {
enable: true,
speed: 3.5,
direction: "none",
random: false,
straight: false,
outMode: "destroy",
attract: {
enable: false,
rotateX: 600,
rotateY: 1200,
},
},
},
//...
//... resize: true, }, modes: { grab: { distance: 400, line_linked: { opacity: 1, }, }, bubble: { distance: 400, size: 40, duration: 2, opacity: 0.8, speed: 3, }, repulse: { distance: 200, }, push: { particles_nb: 4, }, remove: { particles_nb: 2, }, trail: { delay: 0.005, quantity: 5, pauseOnStop: true, }, }, }, retina_detect: true, fullScreen: { enable: true, zIndex: 100, }, fpsLimit: 60, particles: { number: { value: 0, density: { enable: true, value_area: 800, }, }, color: { value: "#0080FF", }, shape: { type: ["circle", "square", "triangle"], }, opacity: { value: { min: 0, max: 1 }, animation: { enable: true, speed: 1, startValue: "max", destroy: "min", }, }, size: { value: { min: 6, max: 12 }, }, links: { enable: false, }, move: { enable: true, speed: 3.5, direction: "none", random: false, straight: false, outMode: "destroy", attract: { enable: false, rotateX: 600, rotateY: 1200, }, }, }, //...
//...  
resize: true,
},
modes: {
grab: {
distance: 400,
line_linked: {
opacity: 1,
},
},
bubble: {
distance: 400,
size: 40,
duration: 2,
opacity: 0.8,
speed: 3,
},
repulse: {
distance: 200,
},
push: {
particles_nb: 4,
},
remove: {
particles_nb: 2,
},
trail: {
delay: 0.005,
quantity: 5,
pauseOnStop: true,
},
},
},
retina_detect: true,
fullScreen: {
enable: true,
zIndex: 100,
},
fpsLimit: 60,
particles: {
number: {
value: 0,
density: {
enable: true,
value_area: 800,
},
},
color: {
value: "#0080FF",
},
shape: {
type: ["circle", "square", "triangle"],
},
opacity: {
value: { min: 0, max: 1 },
animation: {
enable: true,
speed: 1,
startValue: "max",
destroy: "min",
},
},
size: {
value: { min: 6, max: 12 },
},
links: {
enable: false,
},
move: {
enable: true,
speed: 3.5,
direction: "none",
random: false,
straight: false,
outMode: "destroy",
attract: {
enable: false,
rotateX: 600,
rotateY: 1200,
},
},
},
//...

執行應用程式將得到以下效果:

使用 onhover 效果建立滑鼠軌跡

處理響應速度

通過 TsParticles,我們還可以定義粒子在不同螢幕尺寸下的行為,如下圖所示:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
responsive: [
{
maxWidth: 1024,
options: {
particles: {
move: {
speed: {
min: 33,
max: 66,
},
},
},
},
},
],
responsive: [ { maxWidth: 1024, options: { particles: { move: { speed: { min: 33, max: 66, }, }, }, }, }, ],
responsive: [
{
maxWidth: 1024,
options: {
particles: {
move: {
speed: {
min: 33,
max: 66,
},
},
},
},
},
],

在上面的程式碼塊中,我們為 maxWidth = 1024px 的螢幕定義了移動速度的最小值為 33,最大值為 66。因此,所有尺寸小於 1024px 的螢幕都將在定義的斷點範圍內對粒子應用屬性。

與其他 React 元件整合

在本節中,我們將學習如何通過其他元件執行的操作來切換粒子動畫。按鈕或完成進度條等操作都可以觸發這些動畫。

按鈕

使用動畫,我們可以為簡單的使用者互動注入活力,例如點選訂閱按鈕或完成表單註冊。要通過按鈕觸發粒子動畫,請按照以下步驟操作:

  • 首先,我們將建立一個新檔案 Button.jsx,其中包含一個按鈕元件,新增必要的匯入,然後建立一個按鈕:
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import React, { useState } from "react";
import Particles from "react-tsparticles";
import { loadFull } from "tsparticles";
import { useCallback } from "react";
const Button = () => {
const [subscribed, setSubscribed] = useState(false);
// confetti particles animation here
return (
<div
style={{
display: "flex",
height: "100vh",
width: "100vw",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
gap: "23px",
background: "black"
}}
>
<button
id="#myButton"
style={{
padding: "10px 23px",
fontWeight: 700,
width: "max-content",
border: "1px solid black",
borderRadius: "12px",
background: subscribed ? "red" : "white",
color: subscribed ? "white" : "black",
transform: "scale(2)",
}}
onClick={() => setSubscribed(!subscribed)}
>
{subscribed ? "Unsubscribe" : "Subscribe"}
</button>
<p style={{ fontSize: "40px", color: "white" }}>
{/* subscription caption */}
{!subscribed
? "Subscribe to my news letter to get regular updates"
: "Thank you for subscribing. Cheers!!!"}
</p>
// return particles component when subscribed is true
</div>
);
};
export default Button;
import React, { useState } from "react"; import Particles from "react-tsparticles"; import { loadFull } from "tsparticles"; import { useCallback } from "react"; const Button = () => { const [subscribed, setSubscribed] = useState(false); // confetti particles animation here return ( <div style={{ display: "flex", height: "100vh", width: "100vw", flexDirection: "column", justifyContent: "center", alignItems: "center", gap: "23px", background: "black" }} > <button id="#myButton" style={{ padding: "10px 23px", fontWeight: 700, width: "max-content", border: "1px solid black", borderRadius: "12px", background: subscribed ? "red" : "white", color: subscribed ? "white" : "black", transform: "scale(2)", }} onClick={() => setSubscribed(!subscribed)} > {subscribed ? "Unsubscribe" : "Subscribe"} </button> <p style={{ fontSize: "40px", color: "white" }}> {/* subscription caption */} {!subscribed ? "Subscribe to my news letter to get regular updates" : "Thank you for subscribing. Cheers!!!"} </p> // return particles component when subscribed is true </div> ); }; export default Button;
import React, { useState } from "react";
import Particles from "react-tsparticles";
import { loadFull } from "tsparticles";
import { useCallback } from "react";
const Button = () => {
const [subscribed, setSubscribed] = useState(false);
// confetti particles animation here
return (
<div
style={{
display: "flex",
height: "100vh",
width: "100vw",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
gap: "23px",
background: "black"
}}
>
<button
id="#myButton"
style={{
padding: "10px 23px",
fontWeight: 700,
width: "max-content",
border: "1px solid black",
borderRadius: "12px",
background: subscribed ? "red" : "white",
color: subscribed ? "white" : "black",
transform: "scale(2)",
}}
onClick={() => setSubscribed(!subscribed)}
>
{subscribed ? "Unsubscribe" : "Subscribe"}
</button>
<p style={{ fontSize: "40px", color: "white" }}>
{/* subscription caption */}
{!subscribed
? "Subscribe to my news letter to get regular updates"
: "Thank you for subscribing. Cheers!!!"}
</p>
// return particles component when subscribed is true
</div>
);
};
export default Button;

之後,我們就可以建立 TsParticles 配置,並設定 Particles 元件在 subscribe 狀態為 true 時顯示:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// pop confetti
const config = {
fullScreen: {
zIndex: 1,
},
emitters: {
position: {
x: 50,
y: 100,
},
rate: {
quantity: 25,
delay: 0.15,
},
spawnColor: {
value: "#FF8000",
animation: {
h: {
enable: true,
offset: {
min: -1.4,
max: 1.4,
},
speed: 0.1,
sync: false,
},
l: {
enable: true,
offset: {
min: 20,
max: 80,
},
speed: 0,
sync: false,
},
},
},
life: {
count: 1,
duration: 7,
delay: 0.6,
},
size: {
width: 0,
height: 0,
},
},
particles: {
color: {
value: ["#1E00FF", "#FF0061", "#E1FF00", "#00FF9E"],
},
move: {
decay: 0.05,
direction: "top",
enable: true,
gravity: {
enable: true,
},
outModes: {
top: "none",
default: "destroy",
},
speed: {
min: 50,
max: 100,
},
},
number: {
value: 0,
},
opacity: {
value: 1,
},
rotate: {
value: {
min: 0,
max: 360,
},
direction: "random",
animation: {
enable: true,
speed: 30,
},
},
tilt: {
direction: "random",
enable: true,
value: {
min: 0,
max: 360,
},
animation: {
enable: true,
speed: 30,
},
},
size: {
value: 8,
animation: {
enable: true,
startValue: "min",
count: 1,
speed: 16,
sync: true,
},
},
roll: {
darken: {
enable: true,
value: 25,
},
enlighten: {
enable: true,
value: 25,
},
enable: true,
speed: {
min: 5,
max: 15,
},
},
wobble: {
distance: 30,
enable: true,
speed: {
min: -7,
max: 7,
},
},
shape: {
type: ["circle", "square"],
options: {},
},
},
};
const particlesInit = useCallback(async (engine) => {
await loadFull(engine);
}, []);
// pop confetti const config = { fullScreen: { zIndex: 1, }, emitters: { position: { x: 50, y: 100, }, rate: { quantity: 25, delay: 0.15, }, spawnColor: { value: "#FF8000", animation: { h: { enable: true, offset: { min: -1.4, max: 1.4, }, speed: 0.1, sync: false, }, l: { enable: true, offset: { min: 20, max: 80, }, speed: 0, sync: false, }, }, }, life: { count: 1, duration: 7, delay: 0.6, }, size: { width: 0, height: 0, }, }, particles: { color: { value: ["#1E00FF", "#FF0061", "#E1FF00", "#00FF9E"], }, move: { decay: 0.05, direction: "top", enable: true, gravity: { enable: true, }, outModes: { top: "none", default: "destroy", }, speed: { min: 50, max: 100, }, }, number: { value: 0, }, opacity: { value: 1, }, rotate: { value: { min: 0, max: 360, }, direction: "random", animation: { enable: true, speed: 30, }, }, tilt: { direction: "random", enable: true, value: { min: 0, max: 360, }, animation: { enable: true, speed: 30, }, }, size: { value: 8, animation: { enable: true, startValue: "min", count: 1, speed: 16, sync: true, }, }, roll: { darken: { enable: true, value: 25, }, enlighten: { enable: true, value: 25, }, enable: true, speed: { min: 5, max: 15, }, }, wobble: { distance: 30, enable: true, speed: { min: -7, max: 7, }, }, shape: { type: ["circle", "square"], options: {}, }, }, }; const particlesInit = useCallback(async (engine) => { await loadFull(engine); }, []);
// pop confetti
const config = {
fullScreen: {
zIndex: 1,
},
emitters: {
position: {
x: 50,
y: 100,
},
rate: {
quantity: 25,
delay: 0.15,
},
spawnColor: {
value: "#FF8000",
animation: {
h: {
enable: true,
offset: {
min: -1.4,
max: 1.4,
},
speed: 0.1,
sync: false,
},
l: {
enable: true,
offset: {
min: 20,
max: 80,
},
speed: 0,
sync: false,
},
},
},
life: {
count: 1,
duration: 7,
delay: 0.6,
},
size: {
width: 0,
height: 0,
},
},
particles: {
color: {
value: ["#1E00FF", "#FF0061", "#E1FF00", "#00FF9E"],
},
move: {
decay: 0.05,
direction: "top",
enable: true,
gravity: {
enable: true,
},
outModes: {
top: "none",
default: "destroy",
},
speed: {
min: 50,
max: 100,
},
},
number: {
value: 0,
},
opacity: {
value: 1,
},
rotate: {
value: {
min: 0,
max: 360,
},
direction: "random",
animation: {
enable: true,
speed: 30,
},
},
tilt: {
direction: "random",
enable: true,
value: {
min: 0,
max: 360,
},
animation: {
enable: true,
speed: 30,
},
},
size: {
value: 8,
animation: {
enable: true,
startValue: "min",
count: 1,
speed: 16,
sync: true,
},
},
roll: {
darken: {
enable: true,
value: 25,
},
enlighten: {
enable: true,
value: 25,
},
enable: true,
speed: {
min: 5,
max: 15,
},
},
wobble: {
distance: 30,
enable: true,
speed: {
min: -7,
max: 7,
},
},
shape: {
type: ["circle", "square"],
options: {},
},
},
};
const particlesInit = useCallback(async (engine) => {
await loadFull(engine);
}, []);

在上面的程式碼塊中,我們建立了一個 subscribed 狀態,用於管理要顯示的文字以及按鈕的 CSS 屬性。在 return 程式碼塊的末尾,新增

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
{subscribed ? <Particles options={config} init={particlesInit} /> : null}
{subscribed ? <Particles options={config} init={particlesInit} /> : null}
{subscribed ? <Particles options={config} init={particlesInit} /> : null}

這樣,我們就可以在點選按鈕時切換 subscribed 值。它會顯示粒子:

訂閱按鈕粒子效果

進度條指示器

進度條指示器是使用者完成任務進度的標誌。這可以是完成課程,甚至是滾動到頁面底部。通過使用動畫,我們可以為使用者提供一個完成任務的標誌,讓他們感到放鬆。與上一節中的按鈕示例類似,我們可以在滑塊達到 “100%” 值時觸發粒子動畫:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import React, { useState, useEffect } from "react";
const Slider = () => {
const [scrolled, setScrolled] = useState(0);
useEffect(() => {
window.onscroll = function () {
var winScroll =
document.body.scrollTop || document.documentElement.scrollTop;
var height =
document.documentElement.scrollHeight -
document.documentElement.clientHeight;
setScrolled((winScroll / height) * 100);
};
}, []);
return (
<div
style={{
display: "flex",
minHeight: "100vh",
flexDirection: "column",
alignItems: "center",
position: "relative",
padding: "0 120px",
background: "#333"
}}
>
<progress
value={scrolled}
max={100}
style={{
width: "80%",
height: "30px",
marginTop: "15px",
position: "fixed",
top: "0",
}}
></progress>
<h1
style={{
marginTop: "80px",
color:"white",
}}
>
{/* content */}
{/* Page content. For this example, I am using random AI generated text */}
</h1>
</div>
);
};
export default Slider;
import React, { useState, useEffect } from "react"; const Slider = () => { const [scrolled, setScrolled] = useState(0); useEffect(() => { window.onscroll = function () { var winScroll = document.body.scrollTop || document.documentElement.scrollTop; var height = document.documentElement.scrollHeight - document.documentElement.clientHeight; setScrolled((winScroll / height) * 100); }; }, []); return ( <div style={{ display: "flex", minHeight: "100vh", flexDirection: "column", alignItems: "center", position: "relative", padding: "0 120px", background: "#333" }} > <progress value={scrolled} max={100} style={{ width: "80%", height: "30px", marginTop: "15px", position: "fixed", top: "0", }} ></progress> <h1 style={{ marginTop: "80px", color:"white", }} > {/* content */} {/* Page content. For this example, I am using random AI generated text */} </h1> </div> ); }; export default Slider;
import React, { useState, useEffect } from "react";
const Slider = () => {
const [scrolled, setScrolled] = useState(0);
useEffect(() => {
window.onscroll = function () {
var winScroll =
document.body.scrollTop || document.documentElement.scrollTop;
var height =
document.documentElement.scrollHeight -
document.documentElement.clientHeight;
setScrolled((winScroll / height) * 100);
};
}, []);
return (
<div
style={{
display: "flex",
minHeight: "100vh",
flexDirection: "column",
alignItems: "center",
position: "relative",
padding: "0 120px",
background: "#333"
}}
>
<progress
value={scrolled}
max={100}
style={{
width: "80%",
height: "30px",
marginTop: "15px",
position: "fixed",
top: "0",
}}
></progress>
<h1
style={{
marginTop: "80px",
color:"white",
}}
>
{/* content */}
{/* Page content. For this example, I am using random AI generated text */}
</h1>
</div>
);
};
export default Slider;

在上面的程式碼塊中,我們建立了一個進度指示器,顯示使用者滾動了頁面的多少部分。當使用者滾動到頁面底部時,我們將觸發粒子動畫:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// dependencies
import Particles from "react-tsparticles";
import { loadFull } from "tsparticles";
import { useCallback } from "react";
// config and particles init function
const config = {
fullScreen: {
enable: true,
},
detectRetina: true,
fpsLimit: 60,
emitters: {
direction: "top",
position: {
y: 100,
x: 50,
},
rate: {
delay: 0.03,
quantity: 1,
},
life: {
count: 0,
duration: 0.1,
delay: 0.1,
},
size: {
width: 100,
height: 0,
},
particles: {
//properties of the main firework particle
number: {
value: 0, //to randomiser the number of particles
},
destroy: {
mode: "split", //to get the fireworks effect
split: {
rate: {
value: 100, //amount of splits
},
particles: {
// setting properties of those particles formed after splitting
color: {
value: [
"#FF0000" /*Red */,
"#0000FF" /*blue */,
"#FFFF00" /*yellow*/,
],
},
opacity: {
value: 1,
animation: {
enable: true,
speed: 0.2,
minimumValue: 0.1,
sync: false,
startValue: "max", //multiple fireworks
destroy: "min",
},
},
shape: {
type: "star",
},
size: {
value: 4,
animation: {
enable: false, //to get the sparkly feeling
},
},
life: {
count: 1, //amount of time
duration: {
value: {
min: 1,
max: 2,
},
},
},
move: {
//all about firework showers
enable: true, // to get the fireworks effect
gravity: {
enable: false, //stops gravity from pulling them up
},
speed: 3, //speed of the fireworks
direction: "none", //direction of the fireworks
outMode: "destroy", // avoids overlapping of fireworks
},
},
},
},
life: {
count: 1,
},
shape: {
type: "line",
},
size: {
value: { min: 1, max: 100 },
animation: {
enable: true,
sync: true,
speed: 150,
startValue: "random",
destroy: "min",
},
},
stroke: {
color: {
value: ["#00FFFF", "#FF8000", "#0080FF"],
},
width: 1,
},
rotate: {
path: true, //single path
},
move: {
enable: true,
gravity: {
acceleration: 15,
enable: true,
inverse: true, //to avoid projectiles and follow a st line
maxSpeed: 100,
},
speed: { min: 10, max: 20 },
outModes: {
default: "destroy",
},
trail: {
// to give the split particle a trail so that we can see its dirn
enable: true,
length: 10,
},
},
},
},
};
const particlesInit = useCallback(async (engine) => {
await loadFull(engine);
}, []);
// dependencies import Particles from "react-tsparticles"; import { loadFull } from "tsparticles"; import { useCallback } from "react"; // config and particles init function const config = { fullScreen: { enable: true, }, detectRetina: true, fpsLimit: 60, emitters: { direction: "top", position: { y: 100, x: 50, }, rate: { delay: 0.03, quantity: 1, }, life: { count: 0, duration: 0.1, delay: 0.1, }, size: { width: 100, height: 0, }, particles: { //properties of the main firework particle number: { value: 0, //to randomiser the number of particles }, destroy: { mode: "split", //to get the fireworks effect split: { rate: { value: 100, //amount of splits }, particles: { // setting properties of those particles formed after splitting color: { value: [ "#FF0000" /*Red */, "#0000FF" /*blue */, "#FFFF00" /*yellow*/, ], }, opacity: { value: 1, animation: { enable: true, speed: 0.2, minimumValue: 0.1, sync: false, startValue: "max", //multiple fireworks destroy: "min", }, }, shape: { type: "star", }, size: { value: 4, animation: { enable: false, //to get the sparkly feeling }, }, life: { count: 1, //amount of time duration: { value: { min: 1, max: 2, }, }, }, move: { //all about firework showers enable: true, // to get the fireworks effect gravity: { enable: false, //stops gravity from pulling them up }, speed: 3, //speed of the fireworks direction: "none", //direction of the fireworks outMode: "destroy", // avoids overlapping of fireworks }, }, }, }, life: { count: 1, }, shape: { type: "line", }, size: { value: { min: 1, max: 100 }, animation: { enable: true, sync: true, speed: 150, startValue: "random", destroy: "min", }, }, stroke: { color: { value: ["#00FFFF", "#FF8000", "#0080FF"], }, width: 1, }, rotate: { path: true, //single path }, move: { enable: true, gravity: { acceleration: 15, enable: true, inverse: true, //to avoid projectiles and follow a st line maxSpeed: 100, }, speed: { min: 10, max: 20 }, outModes: { default: "destroy", }, trail: { // to give the split particle a trail so that we can see its dirn enable: true, length: 10, }, }, }, }, }; const particlesInit = useCallback(async (engine) => { await loadFull(engine); }, []);
// dependencies
import Particles from "react-tsparticles";
import { loadFull } from "tsparticles";
import { useCallback } from "react";
// config and particles init function
const config = {
fullScreen: {
enable: true,
},
detectRetina: true,
fpsLimit: 60,
emitters: {
direction: "top",
position: {
y: 100,
x: 50,
},
rate: {
delay: 0.03,
quantity: 1,
},
life: {
count: 0,
duration: 0.1,
delay: 0.1,
},
size: {
width: 100,
height: 0,
},
particles: {
//properties of the main firework particle
number: {
value: 0, //to randomiser the number of particles
},
destroy: {
mode: "split", //to get the fireworks effect
split: {
rate: {
value: 100, //amount of splits
},
particles: {
// setting properties of those particles formed after splitting
color: {
value: [
"#FF0000" /*Red */,
"#0000FF" /*blue */,
"#FFFF00" /*yellow*/,
],
},
opacity: {
value: 1,
animation: {
enable: true,
speed: 0.2,
minimumValue: 0.1,
sync: false,
startValue: "max", //multiple fireworks
destroy: "min",
},
},
shape: {
type: "star",
},
size: {
value: 4,
animation: {
enable: false, //to get the sparkly feeling
},
},
life: {
count: 1, //amount of time
duration: {
value: {
min: 1,
max: 2,
},
},
},
move: {
//all about firework showers
enable: true, // to get the fireworks effect
gravity: {
enable: false, //stops gravity from pulling them up
},
speed: 3, //speed of the fireworks
direction: "none", //direction of the fireworks
outMode: "destroy", // avoids overlapping of fireworks
},
},
},
},
life: {
count: 1,
},
shape: {
type: "line",
},
size: {
value: { min: 1, max: 100 },
animation: {
enable: true,
sync: true,
speed: 150,
startValue: "random",
destroy: "min",
},
},
stroke: {
color: {
value: ["#00FFFF", "#FF8000", "#0080FF"],
},
width: 1,
},
rotate: {
path: true, //single path
},
move: {
enable: true,
gravity: {
acceleration: 15,
enable: true,
inverse: true, //to avoid projectiles and follow a st line
maxSpeed: 100,
},
speed: { min: 10, max: 20 },
outModes: {
default: "destroy",
},
trail: {
// to give the split particle a trail so that we can see its dirn
enable: true,
length: 10,
},
},
},
},
};
const particlesInit = useCallback(async (engine) => {
await loadFull(engine);
}, []);

在上面的程式碼塊中,我們匯入了 TsParticles 依賴項,併為之前的煙花動畫建立了一個配置。為了在進度已滿時顯示動畫,我們需要設定一個條件,檢查 scrolled 的值是否為 100,然後渲染 Particles 元件:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
{scrolled === 100 ? (
<Particles options={config} init={particlesInit} />
) : null}
{scrolled === 100 ? ( <Particles options={config} init={particlesInit} /> ) : null}
{scrolled === 100 ? (
<Particles options={config} init={particlesInit} />
) : null}

最終結果:

進度條粒子效果

小結

在本文中,我們討論了 React TsParticles 庫及其融入網路應用時的視覺效果。我們還展示了在 React 應用程式中設定和實現 TsParticles 的步驟。此外,我們還討論了使用使用者互動自定義粒子動畫行為以及與其他 React 元件的整合。

評論留言