Fireworks
ようこそ、Sky Adventureへ。銀河系で最高の花火を提供する未来の会社です! 🎇
Three.js、React Three Fiber、およびVFXエンジンを使用して、私たちの花火を紹介する3Dウェブサイトを作成します。
これが一緒に作成するものです!
スタータープロジェクト
私たちのスタータープロジェクトにはすでに以下が含まれています:
- 美しい浮島から花火を打ち上げるための基本的なReact Three Fiberセットアップ。
- モデル(後に花火も)の光をブームさせるポストプロセシングエフェクト。
- 後で花火を打ち上げるための3つのボタンを含む Tailwind CSS を使ったシンプルなUI。
スタータープロジェクトを実行するときに得られるものがこちらです。
花火
花火を作成するために、前のレッスンで構築したVFXエンジンを使用します。このエンジンを使用すると、さまざまな動作を持つ複数のパーティクルシステムを作成して管理できます。
useFireworks
花火を効率的に管理するために、useFireworks
というカスタムフックを作成します。このフックは花火の作成と管理を行います。
まず、プロジェクトにzustandライブラリを追加します:
yarn add zustand
次に、hooks
というフォルダにuseFireworks.js
という新しいファイルを作成します:
import { create } from "zustand"; const useFireworks = create((set, get) => { return { fireworks: [], }; }); export { useFireworks };
空の花火配列を持つシンプルなストアです。
花火を作成するメソッドを追加しましょう:
// ... import { randFloat, randInt } from "three/src/math/MathUtils.js"; const useFireworks = create((set) => { return { fireworks: [], addFirework: () => { set((state) => { return { fireworks: [ ...state.fireworks, { id: `${Date.now()}-${randInt(0, 100)}-${state.fireworks.length}`, position: [0, 0, 0], velocity: [randFloat(-8, 8), randFloat(5, 10), randFloat(-8, 8)], delay: randFloat(0.8, 2), color: ["skyblue", "pink"], }, ], }; }); }, }; }); // ...
addFirework
は、新しい花火を以下の属性でストアに追加します:
id
: Reactコンポーネント内でキーとして使用するユニークな識別子。position
: 花火が始まる位置。velocity
: 爆発前の花火の方向と速度。delay
: 花火が爆発するまでの時間。color
: 花火爆発のパーティクルに使用する色の配列。
これで、UIにこのフックを接続して花火を打ち上げることができます。
UI.jsx
を開き、addFirework
メソッドをボタンに接続します:
import { useFireworks } from "../hooks/useFireworks"; export const UI = () => { const addFirework = useFireworks((state) => state.addFirework); return ( <section className="fixed inset-0 z-10 flex items-center justify-center"> {/* ... */} <div // ... > {/* ... */} <div className="flex gap-4"> <button // .. onClick={addFirework} > 🎆 Classic </button> <button // .. onClick={addFirework} > 💖 Love </button> <button // .. onClick={addFirework} > 🌊 Sea </button> </div> {/* ... */} </div> </section> ); };
動作を確認するために、Fireworks.jsx
コンポーネントを作成します。今はコンソールに花火をログ表示するだけにします:
import { useFireworks } from "../hooks/useFireworks"; export const Fireworks = () => { const fireworks = useFireworks((state) => state.fireworks); console.log(fireworks); };
そして、Experience
コンポーネントに追加します:
// ... import { Fireworks } from "./Fireworks"; export const Experience = () => { // ... return ( <> {/* ... */} <Float speed={0.6} rotationIntensity={2} position-x={4} floatIntensity={2} > <Fireworks /> <Gltf src="/models/SkyIsland.glb" /> </Float> {/* ... */} </> ); };
Fireworks
コンポーネントをインポートし、<Float />
コンポーネント内のSkyIslandの隣に追加します。
ボタンを押すと、コンソールに花火が正しくストアに追加されていることが確認できます。
シーンに表現する前に、花火のライフサイクルを管理する必要があります。現在、花火は追加されるだけで削除されません。
useFireworks
フック内のaddFirework
メソッドで、一定時間経過後に花火を削除するためにsetTimeout
を追加することができます。
まず、花火が出現した時間を知る必要があります。花火オブジェクトにtime
プロパティを追加します:
{ id: `${Date.now()}-${randInt(0, 100)}-${state.fireworks.length}`, // ... time: Date.now(), },
次にsetTimeout
を呼び出し、爆発して消えた花火を削除します:
addFirework: () => { set((state) => { // ... }); setTimeout(() => { set((state) => ({ fireworks: state.fireworks.filter( (firework) => Date.now() - firework.time < 4000 // 最大遅延2秒 + パーティクルの最大寿命2秒 ), })); }, 4000); },
4秒以上経過した花火をフィルタリングします。この方法で、まだアクティブな花火を維持します。
花火の最終設定に応じて時間を調整してください。
ボタンを押すと、一定時間後にコンソールで花火が正しく削除されていることが確認できます。
これで、あなたが待ち望んでいた部分、シーン内で花火を作成することができます!
VFXエンジン (Wawa VFX)
前のレッスンからコンポーネントをコピー/ペーストしないように、VFXエンジンをnpmパッケージとして公開しました: Wawa VFX。以下のコマンドを実行してインストールできます:
yarn add wawa-vfx@^1.0.0
@^1.0.0
を使用することで、常にパッケージのメジャーバージョン1を使用しつつ、最新のマイナーおよびパッチバージョンを含めることができます。これにより、互換性を損なうことなく、最新の機能やバグ修正を享受できます。
これでプロジェクトで<VFXParticles />
と<VFXEmitter />
を使用することができます!
エクスペリエンスにおいて、シーンにVFXParticles
コンポーネントを追加してみましょう:
// ... import { VFXParticles } from "wawa-vfx"; export const Experience = () => { const controls = useRef(); return ( <> {/* ... */} <VFXParticles name="firework-particles" settings={{ nbParticles: 100000, gravity: [0, -9.8, 0], renderMode: "billboard", intensity: 3, }} /> <EffectComposer> <Bloom intensity={1.2} luminanceThreshold={1} mipmapBlur /> </EffectComposer> </> ); };
VFXParticles
コンポーネントを次の設定で追加します:
100000
個のパーティクル。制限に達した場合、最も古いパーティクルが削除されますが、同時に多くの花火を表示するには十分です。- パーティクルに重力をシミュレートするための
gravity
。-9.8
は地球の重力です。 (でも待って、ここは宇宙だよ!👀) - 常にカメラに向くように
renderMode
をbillboard
に。 - 夜空でパーティクルを輝かせるために
intensity
を3
に。
<VFXParticles />
コンポーネントの配置場所はそれほど重要ではありません。ただし、シーンのトップレベルに配置してください。
そして、VFXParticles
の横にVFXEmitter
コンポーネントを追加し、debug
モードで爆発の形を整え、ビジュアルコントロールにアクセスできるようにしましょう:
// ... import { VFXEmitter, VFXParticles } from "wawa-vfx"; export const Experience = () => { const controls = useRef(); return ( <> {/* ... */} <VFXParticles name="firework-particles" settings={{ nbParticles: 100000, gravity: [0, -9.8, 0], renderMode: "billboard", intensity: 3, }} /> <VFXEmitter emitter="firework-particles" debug /> {/* ... */} </> ); };
emitter
プロップをVFXParticles
コンポーネントと同じname
に設定し、debug
をtrue
にしてコントロールを表示できるようにしてください。
*花火の爆発の最初のバージョンを作成します。*💥
設定に満足したら、VFXEmitter
コンポーネントからdebug
プロップを削除し、エクスポートボタンを押して、VFXEmitter
コンポーネントに設定を貼り付けます。
<VFXEmitter emitter="firework-particles" settings={{ nbParticles: 5000, delay: 0, spawnMode: "burst", colorStart: ["skyblue", "pink"], particlesLifetime: [0.1, 2], size: [0.01, 0.4], startPositionMin: [-0.1, -0.1, -0.1], startPositionMax: [0.1, 0.1, 0.1], directionMin: [-1, -1, -1], directionMax: [1, 1, 1], startRotationMin: [degToRad(-90), 0, 0], startRotationMax: [degToRad(90), 0, 0], rotationSpeedMin: [0, 0, 0], rotationSpeedMax: [3, 3, 3], speed: [1, 12], }} />
VFXエンジンに花火を接続する準備が整いました!
Fireworks explosion
Fireworks.jsx
ファイル内で、1つの花火を表すFirework
コンポーネントを作成しましょう。
// ... import { useRef } from "react"; import { VFXEmitter } from "wawa-vfx"; export const Fireworks = () => { // ... }; const Firework = ({ velocity, delay, position, color }) => { const ref = useRef(); return ( <> <group ref={ref} position={position}> <VFXEmitter emitter="firework-particles" settings={{ nbParticles: 5000, delay: 0, spawnMode: "burst", colorStart: ["skyblue", "pink"], particlesLifetime: [0.1, 2], size: [0.01, 0.4], startPositionMin: [-0.1, -0.1, -0.1], startPositionMax: [0.1, 0.1, 0.1], directionMin: [-1, -1, -1], directionMax: [1, 1, 1], startRotationMin: [degToRad(-90), 0, 0], startRotationMax: [degToRad(90), 0, 0], rotationSpeedMin: [0, 0, 0], rotationSpeedMax: [3, 3, 3], speed: [1, 12], }} /> </group> </> ); };
単にExperience
コンポーネントからVFXEmitter
を切り取って、Firework
コンポーネントに貼り付けます。
シーン内でposition
やvelocity
に基づいて花火を動かせるように、それを<group />
でラップします。
React Three Fiber: The Ultimate Guide to 3D Web Development
✨ You have reached the end of the preview ✨
Go to the next level with Three.js and React Three Fiber!
Get full access to this lesson and the complete course when you enroll:
- 🔓 Full lesson videos with no limits
- 💻 Access to the final source code
- 🎓 Course progress tracking & completion
- 💬 Invite to our private Discord community
One-time payment. Lifetime updates included.