สร้าง scene ด้วย react-three-fiber

สร้าง 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 เช่นกัน

Leave a Reply

Your email address will not be published.