เจาะลึก React และ Three.js โดยใช้ react-three-fiber

เผยแพร่แล้ว: 2022-03-10
สรุปโดยย่อ ↬ react-three-fiber เป็นโปรแกรมเรนเดอร์ Three.js อันทรงพลังที่ช่วยเรนเดอร์โมเดล 3 มิติและแอนิเมชั่นสำหรับ React และแอปพลิเคชันดั้งเดิม ในบทช่วยสอนนี้ คุณจะได้เรียนรู้วิธีกำหนดค่าและสร้างโมเดล 3 มิติในแอปพลิเคชัน React

วันนี้ เราจะมาเรียนรู้วิธีกำหนดค่าและใช้ react-three-fiber สำหรับการสร้างและแสดงโมเดล 3 มิติและแอนิเมชั่นในแอปพลิเคชัน React และ React Native

บทช่วยสอนนี้มีไว้สำหรับนักพัฒนาที่ต้องการเรียนรู้เพิ่มเติมเกี่ยวกับแอนิเมชั่นโมเดล 3 มิติในเว็บโดยใช้ React และสำหรับใครก็ตามที่มีข้อจำกัดกับ Three.js เช่น ไม่สามารถสร้างแคนวาสได้ ผูกเหตุการณ์ของผู้ใช้ เช่น เหตุการณ์การ click และเริ่มการวนรอบการเรนเดอร์ react-three-fiber - react-three-fiber มาพร้อมกับวิธีการเหล่านี้ เรากำลังจะสร้างโมเดล 3 มิติเพื่อให้เข้าใจถึงวิธีการสร้างโมเดล Three.js 3D โดยใช้ react-three-fiber

เริ่มต้นใช้งาน react-three-fiber

Three.js เป็นไลบรารีที่ช่วยให้สร้างกราฟิก 3 มิติในเบราว์เซอร์ได้ง่ายขึ้น โดยใช้ผ้าใบ + WebGL เพื่อแสดงโมเดล 3 มิติและแอนิเมชั่น คุณสามารถเรียนรู้เพิ่มเติมได้ที่นี่

react-three-fiber เป็น React renderer สำหรับ Three.js บนเว็บและ react-native เป็นการเพิ่มความเร็วที่คุณสร้างแบบจำลอง 3 มิติและแอนิเมชั่นด้วย Three.js ตัวอย่างบางส่วนของไซต์ที่มีโมเดล 3 มิติและแอนิเมชั่น สามารถพบได้ที่นี่ react-three-fiber ช่วยลดเวลาที่ใช้กับแอนิเมชั่นเนื่องจากส่วนประกอบที่ใช้ซ้ำได้ เหตุการณ์ที่ผูกมัด และการแสดงวนซ้ำ อันดับแรก เรามาดูกันว่า Three.js คืออะไร

react-three-fiber ช่วยให้เราสร้างส่วนประกอบของโค้ด threeJS โดยใช้สถานะ React, hooks และ props นอกจากนี้ยังมาพร้อมกับองค์ประกอบต่อไปนี้:

องค์ประกอบ คำอธิบาย
mesh คุณสมบัติที่ช่วยกำหนดรูปร่างของโมเดลของเรา
hooks react-three-fiber กำหนด hooks ที่ช่วยให้เราเขียนฟังก์ชันที่ช่วยกำหนดเหตุการณ์ของผู้ใช้ เช่น onClick และ onPointOver
วนตามคอมโพเนนต์และเรนเดอร์ react-three-fiber เป็นส่วนประกอบและแสดงผลตามการเปลี่ยนแปลงในสถานะหรือร้านค้า
เพิ่มเติมหลังกระโดด! อ่านต่อด้านล่าง↓

วิธีใช้ react-three-fiber

ในการใช้ react-three-fiber คุณเริ่มต้นด้วยการใช้คำสั่งด้านล่าง:

NPM

 npm i three react-three-fiber

เส้นด้าย

 yarn add three react-three-fiber

หมายเหตุ : เพื่อให้ react-three-fiber ทำงานได้ คุณจะต้องติดตั้ง three (Three.js) ตามที่เราดำเนินการข้างต้น

การสร้างแบบจำลอง React 3D Ludo Dice และโครงการแอนิเมชั่น

ที่นี่เราจะสร้างแบบจำลองลูกเต๋าลูโด 3 มิติโดยใช้ react-three-fiber อย่างที่เรามีในวิดีโอด้านล่าง

เราจะใช้ create-react-app เพื่อเริ่มต้นโปรเจ็กต์ ให้รันคำสั่งด้านล่างบนเทอร์มินัลของเรา

 create-react-app react-three-fiber-ludo-model

คำสั่งด้านบนเริ่มต้นโปรเจ็กต์ React ภายในเครื่องของเรา ต่อไป cd ลงในไดเร็กทอรีและติดตั้งแพ็คเกจ react-three-fiber และ three

 cd react-three-fiber-ludo-model npm i three react-three-fiber

เมื่อติดตั้งแพ็คเกจแล้ว มาเริ่มเซิร์ฟเวอร์การพัฒนาของเราโดยใช้คำสั่ง

 npm start

คำสั่งข้างต้นควรเริ่มต้นเซิร์ฟเวอร์การพัฒนาโครงการของเราในเบราว์เซอร์ของเรา ต่อไป ให้เปิดโครงการของเราในโปรแกรมแก้ไขข้อความที่เราเลือก ภายในโฟลเดอร์โครงการ src ของเรา ให้ลบไฟล์ต่อไปนี้: App.css , App.test.js , serviceWorker.js และ setupTests.js ต่อไป มาลบโค้ดทั้งหมดที่อ้างอิงถึงไฟล์ที่ถูกลบใน App.js ของเรา

สำหรับโปรเจ็กต์นี้ เราจะต้องมีองค์ประกอบ Box สำหรับลูกเต๋าลูโดและส่วนประกอบ App ของเราที่ได้รับจาก React

การสร้างส่วนประกอบ Box

องค์ประกอบของ Box จะประกอบด้วยรูปร่างสำหรับลูกเต๋าลูโด รูปภาพของลูกเต๋าลูโด และสถานะที่จะหมุนตลอดเวลา อันดับแรก มานำเข้าแพ็คเกจทั้งหมดที่เราต้องการสำหรับองค์ประกอบ Box ด้านล่าง

 import React, { useRef, useState, useMemo } from "react"; import { Canvas, useFrame } from "react-three-fiber"; import * as THREE from "three"; import five from "./assets/five.png";

ในโค้ดด้านบนนี้ เรากำลังนำเข้า useRef , useState และ useMemo เราจะใช้ useRef hook เพื่อเข้าถึงเมชของลูกเต๋าและ useState hook เพื่อตรวจสอบสถานะแอ็คทีฟของ ludo dice useMemo hook จะใช้คืนหมายเลขบนลูกเต๋า ต่อไป เรากำลังนำเข้า Canvas และ useFrame จาก react-three-fiber canvas ใช้เพื่อวาดกราฟิกบนเบราว์เซอร์ ในขณะที่ useFrame อนุญาตให้ส่วนประกอบเชื่อมต่อเข้ากับ render-loop ซึ่งทำให้องค์ประกอบหนึ่งสามารถแสดงผลได้ เนื้อหาของผู้อื่น ต่อไป เรานำเข้าแพ็คเกจ three ชุด จากนั้นเรานำเข้าภาพนิ่งของลูกเต๋าลูโด

ต่อไปสำหรับเราคือการเขียนตรรกะสำหรับองค์ประกอบ Box ของเรา อันดับแรก เราจะเริ่มด้วยการสร้างองค์ประกอบการทำงานและเพิ่มสถานะให้กับองค์ประกอบของเรา มาทำกันด้านล่าง

 const Box = (props) => { const mesh = useRef(); const [active, setActive] = useState(false); useFrame(() => { mesh.current.rotation.x = mesh.current.rotation.y += 0.01; }); const texture = useMemo(() => new THREE.TextureLoader().load(five), []); return ( <Box /> ); }

ในโค้ดด้านบน เรากำลังสร้างองค์ประกอบ Box ด้วย props ต่อไป เราสร้าง ref ที่เรียกว่า mesh โดยใช้ useRef hook เราทำสิ่งนี้เพื่อให้เราสามารถส่งคืนเมชเดิมได้ทุกครั้ง

ตาข่ายเป็นองค์ประกอบภาพในฉาก เป็นวัตถุ 3 มิติที่ประกอบเป็นรูปหลายเหลี่ยมสามเหลี่ยม มักสร้างโดยใช้ เรขาคณิต ซึ่งใช้ในการกำหนดรูปร่างของแบบจำลองและ วัสดุ ที่กำหนดลักษณะที่ปรากฏของแบบจำลอง คุณสามารถ เรียนรู้เกี่ยวกับ Mesh ที่นี่ คุณยังสามารถเรียนรู้เพิ่มเติมเกี่ยวกับ useRef hook ที่นี่

หลังจากเริ่มต้น mesh เราจำเป็นต้องเริ่มต้นสถานะสำหรับแอปพลิเคชันของเราโดยใช้ useState hook ที่นี่เราตั้งค่าสถานะโฮเวอร์และแอ็คทีฟของแอปพลิเคชันเป็นเท็จ

ต่อไป เราใช้ useFrame hook จาก react-three-fiber เพื่อหมุนตาข่าย (ludo dice) โดยใช้รหัสด้านล่าง

 mesh.current.rotation.x = mesh.current.rotation.y += 0.01;

ที่นี่ เรากำลังหมุนตำแหน่งปัจจุบันของตาข่ายทุกๆ 0.01 วินาที ซึ่งทำขึ้นเพื่อให้การหมุนมีภาพเคลื่อนไหวที่ดี

 const texture = useMemo(() => new THREE.TextureLoader().load(five), []);

ในโค้ดด้านบนนี้ เรากำลังสร้างค่าคงที่ที่เรียกว่า texture เจอร์ และส่งผ่าน useMemo hook แบบ react เป็นฟังก์ชันเพื่อโหลดการทอยลูกเต๋าใหม่ ที่นี่ useMemo เพื่อจดจำภาพลูกเต๋าและหมายเลขของมัน คุณสามารถเรียนรู้เกี่ยวกับ useMemo hook ได้ที่นี่

ต่อไป เราต้องการแสดงองค์ประกอบ Box บนเบราว์เซอร์และเพิ่มกิจกรรมของเรา เราทำที่ด้านล่าง

 const Box = (props) => { return ( <mesh {...props} ref={mesh} scale={active ? [2, 2, 2] : [1.5, 1.5, 1.5]} onClick={(e) => setActive(!active)} > <boxBufferGeometry args={[1, 1, 1]} /> <meshBasicMaterial attach="material" transparent side={THREE.DoubleSide}> <primitive attach="map" object={texture} /> </meshBasicMaterial> </mesh> ); }

ในโค้ดด้านบน เรากำลังส่งคืนส่วนประกอบ Box ของเราและห่อไว้ใน mesh เราส่งผ่านคุณสมบัติทั้งหมดของส่วนประกอบ Box โดยใช้ตัวดำเนินการ spread จากนั้นเราอ้างอิง mesh โดยใช้ useRef hook ต่อไป เราใช้คุณสมบัติ scale จาก Three.js เพื่อกำหนดขนาดของกล่องลูกเต๋าเมื่อเปิดใช้งานเป็น 2 และ 1.5 เมื่อไม่ได้ใช้งาน สุดท้ายแต่ไม่ท้ายสุด เราได้เพิ่มเหตุการณ์ onClick เพื่อตั้งค่า state เป็น active หากไม่ได้ตั้งค่าเป็นค่าเริ่มต้น

 <boxBufferGeometry args={[1, 1, 1]} />

เพื่อแสดงกล่องลูกเต๋า เราแสดงผลองค์ประกอบ boxBufferGeometry จาก Three.js, boxBufferGeometry ช่วยให้เราวาดเส้นและจุดเช่นกล่อง เราใช้ args เพื่อส่งผ่านตัวสร้างเช่นขนาดของกล่องเรขาคณิต

 <meshBasicMaterial attach="material" transparent side={THREE.DoubleSide}>

meshBasicMaterial จาก Three.js ใช้ในการวาดรูปทรงเรขาคณิตในรูปแบบง่ายๆ ที่นี่เราส่งแอตทริบิวต์ attach และส่งอุปกรณ์ประกอบฉาก THREE.DoubleSide ไปยังแอตทริบิวต์ side THREE.DoubleSide กำหนดด้านหรือช่องว่างที่ควรแสดงโดย react-three-fiber

 <primitive attach="map" object={texture} />

องค์ประกอบ primitive จาก Three.js ใช้ในการวาดกราฟ 3 มิติ เราแนบคุณสมบัติแผนที่เพื่อรักษารูปร่างดั้งเดิมของลูกเต๋าลูโด ต่อไป เราจะสร้างองค์ประกอบ Box ของเราในไฟล์ App.js และทำกล่องลูกเต๋าลูโด 3 มิติให้สมบูรณ์ ส่วนประกอบของคุณควรมีลักษณะคล้ายกับภาพด้านล่าง

ส่วนประกอบกล่องสำหรับ ludo 3D box

แสดงผล 3D Ludo Dice Box

ในส่วนนี้ เราจะสร้างองค์ประกอบ Box ของเราใน App.js และทำกล่อง 3d ludo ให้สมบูรณ์ อันดับแรก ให้สร้างองค์ประกอบ App และห่อด้วยแท็ก Canvas เพื่อสร้างโมเดล 3 มิติของเรา ลองทำกันด้านล่าง

 const App = () => { return ( <Canvas> </Canvas> ); } export default App;

ต่อไป มาเพิ่มไฟให้กับกล่องกัน react-three-fiber ให้ส่วนประกอบ 3 อย่างแก่โมเดลของเราซึ่งมีดังนี้

  • ambientLight
    ใช้สำหรับให้แสงวัตถุทั้งหมดในฉากหรือแบบจำลองเท่าๆ กัน โดยรับอุปกรณ์ประกอบฉาก เช่น ความเข้มของแสง ซึ่งจะทำให้ร่างกายของลูกเต๋าลูโดสว่างขึ้น
  • spotLight
    แสงนี้ถูกปล่อยออกมาจากทิศทางเดียว และจะเพิ่มขึ้นเมื่อขนาดของวัตถุเพิ่มขึ้น ซึ่งจะทำให้จุดของลูกเต๋าลูโดสว่างขึ้น
  • pointLight
    การทำงานนี้คล้ายกับแสงของหลอดไฟ แสงถูกปล่อยออกมาจากจุดเดียวไปยังทุกทิศทาง ซึ่งจำเป็นสำหรับสถานะแอ็คทีฟของแอปพลิเคชันของเรา

มาปรับใช้ข้างต้นกับแอปพลิเคชันของเราด้านล่าง

 const App = () => { return ( <Canvas> <ambientLight intensity={0.5} /> <spotLight position={[10, 10, 10]} angle={0.15} penumbra={1} /> <pointLight position={[-10, -10, -10]} /> </Canvas> ); } export default App;

ในโค้ดด้านบน เรานำเข้าส่วนประกอบ ambientLight จาก react-three-fiber และเพิ่มความเข้ม 0.5 ลงไป ต่อไปเราได้เพิ่มตำแหน่งและมุมให้กับส่วนประกอบ spotLight และ pointLight ของเรา ขั้นตอนสุดท้ายสำหรับแอปพลิเคชันของเราคือสร้างองค์ประกอบกล่องและเพิ่มตำแหน่งให้กับกล่องลูกเต๋าลูโด เราจะทำในโค้ดด้านล่าง

 <Box position={[-1.2, 0, 0]} /> <Box position={[2.5, 0, 0]} />

เมื่อเสร็จแล้ว ludo 3D dice ของคุณควรมีลักษณะคล้ายกับภาพด้านล่าง:

กล่องลูกเต๋าลูโด 3 มิติ

การสาธิตการทำงานมีอยู่ใน CodeSandbox

บทสรุป

react-three-fiber ทำให้การเรนเดอร์โมเดล 3 มิติและแอนิเมชั่นสร้างได้ง่ายขึ้นสำหรับแอปพลิเคชัน React และ React Native ด้วยการสร้างกล่องลูกเต๋า 3D ludo เราได้เรียนรู้เกี่ยวกับพื้นฐานของ Three.js ควบคู่ไปกับส่วนประกอบและประโยชน์ของ react-three-fiber รวมถึงวิธีใช้งาน

คุณสามารถดำเนินการเพิ่มเติมได้โดยการสร้างโมเดล 3 มิติและแอนิเมชั่นในแอปพลิเคชัน React และ Native โดยใช้ react-three-fiber ด้วยตัวคุณเอง ฉันชอบที่จะเห็นสิ่งใหม่ ๆ ที่คุณคิด!

คุณสามารถอ่านเพิ่มเติมเกี่ยวกับ Three.js และ react-three-fiber ได้ในข้อมูลอ้างอิงด้านล่าง

แหล่งข้อมูลที่เกี่ยวข้อง

  • เอกสารประกอบของ Three.js
  • ปัจจัยพื้นฐาน Three.js
  • React-Three-fiber GitHub repo โดย Poimandres
  • เอกสารประกอบปฏิกิริยาสามไฟเบอร์
  • React Hooks (useState, useMemo, ฯลฯ ) เอกสารอย่างเป็นทางการ