Jejak
Mari kita menjelajahi dunia jejak! Jejak adalah cara yang bagus untuk menambahkan rasa gerakan ke dalam adegan Anda. Mereka dapat digunakan untuk membuat berbagai efek, seperti jejak cahaya, jejak asap, atau bahkan jejak dari objek yang bergerak.
Berikut adalah proyek akhir yang akan kita bangun bersama:
Kita akan mulai dengan membuat efek jejak sederhana menggunakan kustom jejak cursor. Kemudian kita akan menjelajahi Trail component dari drei untuk membuat komet yang Anda lihat di pratinjau.
Proyek awal
Proyek awal berisi banyak hal yang sudah kita bahas dalam pelajaran sebelumnya:
- Komponen ScrollControls untuk menangani scroll dan gerakan kamera serta animasi terkait. Jika Anda perlu penyegaran, Anda dapat memeriksa pelajaran Scroll yang didedikasikan.
- Efek pasca-pemrosesan seperti Bloom dan Vignette, dengan tambahan cantik berupa efek GodRays. Lihat pelajaran Post processing jika Anda perlu penyegaran.
<StarrySky />
yang kita bangun dalam pelajaran Partikel dengan parameter yang disesuaikan.
Selain itu, saya menggunakan Tailwind CSS untuk secara cepat merancang UI. Jika Anda tidak familiar dengan Tailwind CSS, Anda dapat melewati bagian antarmuka pengguna dan fokus pada bagian Threejs.
Model WawaCoin dan WawaCard dibuat di dalam negeri dan tersedia di proyek awal. Saya menggunakan MeshTransmissionMaterial dari drei untuk menciptakan tampilan futuristik ini.
Silakan transformasi adegan sesuai keinginan Anda. Anda dapat dengan bebas menggunakan kembali bagian mana pun dari proyek ini dalam proyek Anda sendiri.
Saya lupa menyebutkan, tetapi isi situs web ini sepenuhnya fiksi. Saya tidak meluncurkan cryptocurrency baru. (Belum? 👀)
Kursor Jejak Kustom
Mari kita mulai dengan membuat efek jejak sederhana yang mengikuti kursor.
Buat file components/Cursor.jsx
baru dan tambahkan kode berikut:
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> </> ); };
Ini adalah bola sederhana yang mengikuti gelombang sinus. Anda dapat menyesuaikan ukuran, warna, intensitas, dan opasitas kursor menggunakan kontrol Leva.
Untuk saat ini kita menggunakan gerakan tetap, ini akan menyederhanakan visualisasi dari jejak. Kita akan menggantinya dengan posisi mouse nanti.
Tambahkan komponen Cursor
ke komponen Experience
:
// ... import { Cursor } from "./Cursor"; export const Experience = () => { // ... return ( <> <Cursor /> {/* ... */} </> ); }; // ...
Kita bisa melihat bola yang bergerak, itu akan menjadi target dari jejak kita.
Komponen SimpleTrail
Group adalah target yang akan diikuti oleh trail kami. Kita akan membuat komponen baru components/SimpleTrail.jsx
untuk menciptakan efek 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> </> ); }
Parameter-parameternya adalah sebagai berikut:
- target: ref dari target yang akan diikuti.
- color: warna dari trail.
- intensity: intensitas emisi dari trail.
- numPoints: jumlah posisi yang akan kita simpan dalam trail. (Semakin tinggi angkanya, semakin panjang trailnya).
- height: tinggi dari trail.
- minDistance: jarak minimum antara dua titik.
- opacity: opasitas dari trail.
- duration: waktu sebelum trail mulai memudar dari ujungnya.
Jangan khawatir jika Anda belum memahami semua parameternya. Kita akan menjelaskannya sambil mengimplementasikan trail.
Impor komponen SimpleTrail
ke dalam komponen Cursor
:
// ... import { SimpleTrail } from "./SimpleTrail"; export const Cursor = () => { // ... return ( <> <group ref={target}>{/* ... */}</group> <SimpleTrail target={target} color={color} intensity={intensity} opacity={opacity} height={size} /> </> ); };
Mesh terdiri dari <planeGeometry />
dengan jumlah segmen yang sama dengan numPoints
. Kita akan memperbarui posisi setiap segmen untuk mengikuti target.
Secara visual, karena ukuran plane kita adalah 1x1, kita bisa melihat kotak, tetapi karena jumlah segmen, kita akan dapat memanipulasi vertices untuk menciptakan efek trail.
Mari kita lihat sisi-sisi plane dengan satu segmen dan plane dengan 20 segmen:
<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>
Kode ini hanya untuk tujuan visualisasi. Anda bisa menghapusnya setelah memahami konsepnya.
Kami memperbesar mereka pada sumbu y untuk melihat perbedaan dalam jumlah segmen.
Anda dapat melihat bahwa plane kiri hanya memiliki 4 vertices sementara plane kanan memiliki lebih banyak lagi. Kami akan memanipulasi vertices ini untuk membangun efek trail.
Kita bisa menggunakan line daripada plane untuk membuat trail, tetapi menggunakan plane memungkinkan kita untuk menciptakan efek yang menarik (Berfungsi lebih baik untuk angin misalnya).
Komponen Trail dari drei menggunakan line, kami tidak ingin mengetik ulang hal yang sama.
Memanipulasi vertices
Kita akan memperbarui posisi vertices dari bidang untuk mengikuti target seiring waktu.
Pertama, kita perlu menyimpan semua posisi target dalam sebuah array. Kita akan menggunakan ref untuk menyimpan posisi-posisi ini.
// ... import * as THREE from "three"; export function SimpleTrail( { // ... } ) { const mesh = useRef(); const positions = useRef( new Array(numPoints).fill(new THREE.Vector3(0, 0, 0)) ); // ... }
Array ini akan selalu memiliki panjang numPoints
dan akan menyimpan posisi-posisi target.
Ketika target bergerak, kita akan menambahkan posisi baru ke bagian depan array, mendorong posisi-posisi lain ke belakang.
Untuk mengimplementasikan ini, kita akan menggunakan hook useFrame untuk memperbarui posisi vertices.
// ... 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(); } }); // ... }
Pertama, kita menghitung jarak antara titik terakhir dan titik saat ini. Jika jaraknya lebih besar dari minDistance
, kita menambahkan titik saat ini ke depan array dengan unshift
dan menghapus titik terakhir dengan pop
.
Sekarang kita perlu memperbarui posisi vertices dari bidang untuk mengikuti posisi 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.