Scie
Immergiamoci nel mondo delle scie! Le scie sono un ottimo modo per aggiungere un senso di movimento alla tua scena. Possono essere utilizzate per creare una varietà di effetti, come scie luminose, scie di fumo o persino la scia di un oggetto in movimento.
Ecco il progetto finale che costruiremo insieme:
Inizieremo creando un semplice effetto di scia utilizzando un cursore di scia personalizzato. Poi esploreremo il Trail componente di drei per realizzare le comete che hai visto nell'anteprima.
Progetto iniziale
Il progetto iniziale contiene molti elementi che abbiamo già trattato nelle lezioni precedenti:
- Il ScrollControls componente per gestire lo scroll e il movimento della telecamera associato e le animazioni. Se hai bisogno di un ripasso, puoi controllare la lezione dedicata allo Scroll.
- Effetti di post-produzione come Bloom e Vignette, con un'interessante aggiunta dell'effetto GodRays. Controlla la lezione Post processing se hai bisogno di un ripasso.
- Il
<StarrySky />
che abbiamo costruito nella lezione Particles con parametri regolati.
Inoltre, ho utilizzato Tailwind CSS per progettare rapidamente l'interfaccia utente. Se non sei familiare con Tailwind CSS, puoi saltare la parte sull'interfaccia utente e concentrarti sulla parte Threejs.
I modelli di WawaCoin e WawaCard sono creati internamente e sono disponibili nel progetto iniziale. Ho utilizzato il MeshTransmissionMaterial di drei per creare questo aspetto futuristico.
Sentiti libero di trasformare la scena a tuo piacimento. Puoi riutilizzare liberamente qualsiasi parte del progetto nei tuoi progetti.
Ho dimenticato di menzionarlo, ma il contenuto del sito è puramente fittizio. Non sto lanciando una nuova criptovaluta. (Ancora? 👀)
Cursore con scia personalizzata
Iniziamo creando un semplice effetto di scia che segue il cursore.
Crea un nuovo file components/Cursor.jsx
e aggiungi il seguente codice:
import { useFrame } from "@react-three/fiber"; import { useControls } from "leva"; import { useRef } from "react"; export const Cursor = () => { const { color, intensity, opacity, size } = useControls("Cursor", { size: { value: 0.2, min: 0.1, max: 3, step: 0.01 }, color: "#dfbcff", intensity: { value: 4.6, min: 1, max: 10, step: 0.1 }, opacity: { value: 0.5, min: 0, max: 1, step: 0.01 }, }); const target = useRef(); useFrame(({ clock }) => { if (target.current) { const elapsed = clock.getElapsedTime(); target.current.position.x = Math.sin(elapsed) * 5; target.current.position.y = Math.cos(elapsed * 2) * 4; target.current.position.z = Math.sin(elapsed * 4) * 10; } }); return ( <> <group ref={target}> <mesh> <sphereGeometry args={[size / 2, 32, 32]} /> <meshStandardMaterial color={color} transparent opacity={opacity} emissive={color} emissiveIntensity={intensity} /> </mesh> </group> </> ); };
È una semplice sfera che segue un'onda sinusoidale. Puoi regolare la dimensione, il colore, l'intensità e l'opacità del cursore utilizzando i controlli Leva.
Per ora utilizziamo un movimento fisso, semplificherà la visualizzazione della scia. Lo sostituiremo in seguito con la posizione del mouse.
Aggiungi il componente Cursor
al componente Experience
:
// ... import { Cursor } from "./Cursor"; export const Experience = () => { // ... return ( <> <Cursor /> {/* ... */} </> ); }; // ...
Possiamo vedere una sfera in movimento, che sarà il bersaglio della nostra scia.
Componente SimpleTrail
Il group è il target che il nostro trail seguirà . Creeremo un nuovo componente components/SimpleTrail.jsx
per creare l'effetto del trail:
import { useRef } from "react"; import * as THREE from "three"; export function SimpleTrail({ target = null, color = "#ffffff", intensity = 6, numPoints = 20, height = 0.42, minDistance = 0.1, opacity = 0.5, duration = 20, }) { const mesh = useRef(); return ( <> <mesh ref={mesh}> <planeGeometry args={[1, 1, 1, numPoints - 1]} /> <meshBasicMaterial color={color} side={THREE.DoubleSide} transparent={true} opacity={opacity} depthWrite={false} /> </mesh> </> ); }
I parametri sono i seguenti:
- target: il ref del target da seguire.
- color: il colore del trail.
- intensity: l'intensità emissiva del trail.
- numPoints: il numero di posizioni che memorizzeremo nel trail. (Più alto è il numero, più lungo sarà il trail).
- height: l'altezza del trail.
- minDistance: la distanza minima tra due punti.
- opacity: l'opacità del trail.
- duration: il tempo prima che il trail inizi a svanire dalla sua estremità .
Non preoccuparti se non comprendi ancora tutti i parametri. Li spiegheremo mentre implementiamo il trail.
Importa il componente SimpleTrail
nel componente Cursor
:
// ... import { SimpleTrail } from "./SimpleTrail"; export const Cursor = () => { // ... return ( <> <group ref={target}>{/* ... */}</group> <SimpleTrail target={target} color={color} intensity={intensity} opacity={opacity} height={size} /> </> ); };
Il mesh è composto da un <planeGeometry />
con un numero di segmenti pari a numPoints
. Aggiorneremo la posizione di ciascun segmento per seguire il target.
Visivamente, poiché la dimensione del nostro piano è 1x1, possiamo vedere un quadrato, ma a causa del numero di segmenti, saremo in grado di manipolare i vertici per creare l'effetto del trail.
Vediamo fianco a fianco un plane con un segmento e un plane con 20 segmenti:
<group position-x={5}> <mesh position-x={4} scale-y={5}> <planeGeometry args={[1, 1, 1, numPoints - 1]} /> <meshBasicMaterial color={"red"} wireframe /> </mesh> <mesh position-x={2} scale-y={5}> <planeGeometry args={[1, 1, 1, 1]} /> <meshBasicMaterial color={"red"} wireframe /> </mesh> </group>
Questo codice è solo a scopo di visualizzazione. Puoi rimuoverlo dopo aver compreso il concetto.
Li scaliamo sull'asse y per vedere la differenza nel numero di segmenti.
Puoi vedere che il piano a sinistra ha solo 4 vertici mentre il piano a destra ne ha molti di più. Manipoleremo questi vertici per costruire l'effetto del trail.
Potremmo utilizzare una line invece di un plane per creare il trail, ma utilizzare un plane ci consente di creare un effetto interessante (Funziona meglio con il vento, per esempio).
Il componente Trail di drei utilizza una line, non vogliamo ricodificare la stessa cosa.
Manipolazione dei vertici
Aggiorneremo la posizione dei vertici del piano per seguire il target nel tempo.
Per prima cosa, sarà necessario memorizzare tutte le posizioni del target in un array. Utilizzeremo un ref per memorizzare le posizioni.
// ... import * as THREE from "three"; export function SimpleTrail( { // ... } ) { const mesh = useRef(); const positions = useRef( new Array(numPoints).fill(new THREE.Vector3(0, 0, 0)) ); // ... }
Questo array avrà sempre una lunghezza di numPoints
e memorizzerà le posizioni del target.
Quando il target si muove, aggiungeremo la nuova posizione all'inizio dell'array, spingendo le altre posizioni alla fine.
Per implementarlo, utilizzeremo l'hook useFrame per aggiornare la posizione dei vertici.
// ... import { useFrame } from "@react-three/fiber"; export function SimpleTrail( { // ... } ) { // ... useFrame(() => { if (!mesh.current || !target?.current) { return; } const curPoint = target.current.position; const lastPoint = positions.current[0]; const distanceToLastPoint = lastPoint.distanceTo(target.current.position); if (distanceToLastPoint > minDistance) { positions.current.unshift(curPoint.clone()); positions.current.pop(); } }); // ... }
Per prima cosa, calcoliamo la distanza tra l'ultimo punto e il punto corrente. Se la distanza è maggiore di minDistance
, aggiungiamo il punto corrente all'inizio dell'array con unshift
e rimuoviamo l'ultimo punto con pop
.
Ora dobbiamo aggiornare la posizione dei vertici del piano per seguire le posizioni del target.
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.