สร้าง scene ด้วย react-three-fiber
react-three-fiber คือ การนำไลบรารี three.js มาประยุกต์ให้ใช้ได้กับ React.js และทางผู้สร้างก็ยังได้อธิบายไว้ใน GitHub Repository ของ React Three Fiber จะไม่มี overhead ที่จะทำให้ช้าลงกับต้นฉบับอย่าง three.js แต่อย่างใด อีกทั้งยังอัพเดตไปพร้อม ๆ กับ three.js
ข้อกำหนดเบื้องต้น
ข้อกำหนดสำหรับบทความนี้คือ คุณควรได้ทำตามบทความ โปรแกรมแรก React กับ Three.js มาก่อน
สร้าง scene ด้วย react-three-fiber
ในบทความที่แล้วเราได้สร้าง กล่องลูกบาศก์สีน้ำเงินเคลื่อนไหว ด้วย Three.js ในบทความนี้ จะได้เรียนรู้ว่าเราสามารถทำสิ่งเดียวกันได้อย่างไรโดยใช้โค้ดน้อยลง ด้วย react-three-fiber
pmndrs / react-three-fiber นี่คือหน้า GitHub สำหรับ Reactor Reviver, Kim Dotcom Slash P.M. และ D-R s slash reactor และ Fiber
ซึ่งปัจจุบันได้อัพเดตจาก react-three-fiber ไปใช้ three @react-three/fiber แล้ว แต่บทความนี้ยังคงใช้ react-three-fiber ในการเรียนรู้การใช้งาน Three.js
เขียนโค้ดโดยใช้ react-three-fiber
เปิดไฟล์ App.js เขียนโค้ดเบื้องต้น และทดสอบการทำงานดังนี้

ผลลัพธ์ ที่เว็บบราวเซอร์

Canvas
Canvas เป็นหนึ่งใน feature ที่มีคุณสมบัติทางด้านกราฟฟิคที่มาพร้อมกับ HTML5 ซึ่ง Canvas สามารถทำให้คุณสามารถสร้างระบบต่างๆ ที่คุณต้องการขึ้นมา ไม่ว่าจะเป็นระบบเกมส์ หรือโปรแกรมวาดภาพบนเว็บ ที่รองรับทุก platform โดย Canvas เป็น Element หนึ่งใน HTML5 จะมีเพียงแค่ 2 attributes คือ width
และ height
(ความกว้างและความสูงของ Canvas) เท่านั้น
นำเข้า Canvas จาก react-three-fiber
import { Canvas } from "react-three-fiber";
ภายในฟังก์ชัน App ส่งค่ากลับเป็น Element Canvas
function App() {
return (
<Canvas>
</Canvas>
);
}
Mesh
Mesh คือการแบ่งชิ้นงานออกเป็นชิ้นส่วนเรขาคณิตเล็กๆ เพื่อให้เราสามารถใช้สูตรคำนวณต่างๆที่เรามีอยู่ได้ Mesh ที่ว่าก็คือวัตถุในโลกของ 3 มิตินั่นเอง วัตถุตัวนี้จะมีองค์ประกอบเป็นรูปสามเหลี่ยมที่เอามาเรียงต่อกัน กลายเป็นรูปหลายเหลี่ยม การ render mesh 1 ก้อน ก็คือการวาดแบบที่เล็กที่สุดที่เรียกว่า draw primitives เป็นการวาดรูปสามเหลี่ยมโดยการดึงข้อมูลของจุดมาทีละสามจุด เรียกว่า vertex มาวาดต่อ ๆ กัน
เพิ่ม Element Mesh ภายใน Canvas
<Canvas>
<mesh>
</mesh>
</Canvas>
BoxGeometry
BoxGeometry เป็นคลาสเรขาคณิตสำหรับทรงลูกบาศก์สี่เหลี่ยมที่มี ‘ความกว้าง’ ‘ความสูง’ และ ‘ความลึก’ ที่กำหนด ในการสร้าง ทรงลูกบาศก์ โดยจะมีศูนย์กลางอยู่ที่จุดกำเนิด และแต่ละขอบจะขนานกับแกนใดแกนหนึ่ง
เพิ่ม boxBufferGeometry ภายใน mesh
<mesh>
<boxBufferGeometry/>
</mesh>
MeshBasicMaterial
MeshBasicMaterial วัสดุสำหรับการวาดรูปทรงเรขาคณิตด้วยวิธีแรเงาแบบเรียบง่าย (แบบแบนหรือแบบโครงลวด) โดยวัสดุนี้ไม่ได้รับผลกระทบจากแสง
เพิ่ม meshBasicMaterial ภายใน mesh
<mesh>
<boxBufferGeometry/>
<meshBasicMaterial/>
</mesh>

ผลลัพธ์ ที่เว็บบราวเซอร์ จะมีกล่องสี่เหลี่ยมสีเทา ปรากฏขึ้นมา

Viewport
viewport คือ ขนาดการแสดงผลของหน้าจอที่ browser ได้ทำการ render website นั้นๆ งั้นบางครั้งถ้าเราอยากจะกำหนดขนาดของ element อะไรก็ตาม เช่น website ที่เป็น One-pagers, full-width grid, typography และอื่นๆ อีกมากมายที่มีผลเกี่ยวข้องกับขนาดของ viewport
ดั้งนั้นหน่วยวัดใหม่นี้จึงเกิดขึ้น คือ
- vh: 1/100th ของความสูงของ viewport
- vw: 1/100th ของความกว้างของ viewport
div คือ แท็กประเภทนึงของ html ใช้สำหรับครอบวัตถุที่เราต้องการ เพื่อจัดรูปแบบต่างๆ ให้กับวัตถุในตำแหน่งนั้นๆ
เพิ่ม div และขนาด viewport ครอบวัตถุ Canvas
<div style={{ height: '100vh', width: '100vw' }}>
<Canvas>
<mesh>
<boxBufferGeometry />
<meshBasicMaterial />
</mesh>
</Canvas>
</div>

ผลลัพธ์ ที่เว็บบราวเซอร์กล่องสี่เหลี่ยมสีเทา จะมีขนาดใหญ่ขึ้น

กำหนดสีของพื้นผิววัสดุเป็นสีน้ำเงิน
<meshBasicMaterial color='blue' />

กำหนดพื้นหลังการแสดงผลเป็นสีดำ
<Canvas style={{background: 'black'}}>

ผลลัพธ์ ที่เว็บบราวเซอร์

ปรับแก้ไขโค้ดโดยใช้ useFrame
นำเข้า useFrame จาก react-three-fiber และสิ่งสำคัญคือต้องทราบว่าเราสามารถเรียกใช้งานได้จากภายใน Canvas เท่านั้น
import { Canvas , useFrame } from "react-three-fiber";
ซึ่งหมายความว่าหากเราต้องการใช้ เราต้องสร้างส่วนประกอบอื่น มาดึง box mesh นี้ออกเป็นส่วนประกอบแยกต่างหากหรือเรียกมันว่ากล่อง const Box
const Box = () => {
useFrame(state => {
console.log(state);
})
return (
<mesh>
<boxBufferGeometry />
<meshBasicMaterial color='blue' />
</mesh>
)
}
function App เรียกใช้งาน Box ได้จากภายใน Canvas
<Canvas style={{ background: 'black' }}>
<Box/>
</Canvas>


useRef
useRef คือ React Hooks ที่สามารถเข้าถึงโดยการ Reference ไปที่ DOM element ใช้กับ Functional component สามารถทำ initialValue (.current) ได้ (function ใน Dom เป็น 1 Component ถ้าเราต้องการเรียกใช้ function ใน Dom จะใช้ Ref เป็นตัวเชื่อมเพื่อเข้าไปดึง function ใน dom)
import { useRef } from 'react';
จากนั้นเพิ่ม ref นี้ให้กับ useRef
const ref = useRef();
เรากำลังจะไปในทุกเฟรม เพื่อเรียก ref .current และ .current เป็นเพียงส่วนหนึ่งของ user ref API และทำให้เราเข้าถึง
<mesh ref={ref}>
ตอนนี้ current เป็น actual mesh object เราจะเรียกการหมุน current rotation X =+ 0.01 และ สิ่งเดียวกันสำหรับ Y
const Box = () => {
const ref = useRef();
useFrame(state => {
ref.current.rotation.x += 0.01;
ref.current.rotation.y += 0.01;
})
โค้ดทั้งหมด ณ.ตอนนี้

import './App.css';
import { Canvas, useFrame } from "react-three-fiber";
import { useRef } from 'react';
const Box = () => {
const ref = useRef();
useFrame(state => {
ref.current.rotation.x += 0.01;
ref.current.rotation.y += 0.01;
})
return (
<mesh ref={ref}>
<boxBufferGeometry />
<meshBasicMaterial color='blue' />
</mesh>
)
}
function App() {
return (
<div style={{ height: '100vh', width: '100vw' }}>
<Canvas style={{ background: 'black' }}>
<Box />
</Canvas>
</div>
);
}
export default App;
ผลลัพธ์การทำงาน
ดูผ่านเว็บไซต์ได้ที่
ที่เว็บบราวเซอร์ คุณจะเห็นกล่องลูกบาศก์สีน้ำเงินเคลื่อนไหว และเมื่อขยายขนาดของ เว็บบราวเซอร์ กล่องลูกบาศก์สีน้ำเงินจะอยู่กึ่งกลางของจอภาพโดยอัตโนมัติ และ ขนาดของฉากก็ขยายตามขนาดของจอภาพโดยอัตโนมัติ เหมือนกับบทความ โปรแกรมแรก React กับ Three.js เช่นกัน
