จัดระเบียบโค้ดด้วย .JSX

จัดระเบียบโค้ดด้วย .JSX

JSX ย่อมาจาก ( JavaScript Syntax eXtension) ซึ่งหมายถึงส่วนเสริมของ Javascript นั่นเองครับ ถูกพัฒนาขึ้นมาใช้กับ React โดยเฉพาะ โดย Syntax นั้นมีความคล้ายคลึงกับ HTML เป็นอย่างมาก แต่สิ่งนึงที่เห็นได้ชัดคือจะเห็นการเขียนโค้ดในลักษณะนี้ในอยู่ในไฟล์ Javascript แทนที่จะเป็นไฟล์ HTML และแยกการทำงานเป็นส่วนๆ เรียกว่า คอมโพเนนท์

คอมโพเนนท์

คอมโพเนนท์สามารถอ้างอิงและใช้งานคอมโพเนนท์อื่นๆได้ ซึ่งทำให้เราสามารถใช้งานคอมโพเนนท์ได้ในทุกระดับเช่น ปุ่ม, ฟอร์ม, กล่องข้อความ หรือแม้กระทั่งทั้งหน้าจอ ทุกสิ่งทุกอย่างใน React นั้นถูกแสดงจากคอมโพเนนท์หลายๆ คอมโพเนนท์ร่วมกัน


ข้อกำหนดเบื้องต้น


ข้อกำหนดสำหรับบทความนี้คือ คุณควรได้ทำตามบทความ  สร้างภาพสามมิติแบบโต้ตอบ (Interactive) มาก่อน


จัดระเบียบโค้ด แยกเป็นไฟล์ คอมโพเนนท์ .jsx

สร้างโฟลเดอร์ components ภายในโฟลเดอร์ src

สร้างไฟล์ Orbit.jsx


สร้างไฟล์ Orbit.jsx ภายในโฟลเดอร์ components เขียนโค้ดดังนี้

import { extend, useThree } from 'react-three-fiber';
import {
    OrbitControls
} from 'three/examples/jsm/controls/OrbitControls';
extend({ OrbitControls });

const Orbit = () => {
    const { camera, gl } = useThree();
    return (
        <orbitControls 
            attach='orbitControls'
            args={[camera, gl.domElement]} 
        />
    )
}

export default Orbit;

ที่ไฟล์ App.js ลบโค้ดออกดังนี้

เพิ่มโค้ด

import Orbit from './components/Orbit';

สร้างไฟล์ Box.jsx

สร้างไฟล์ Box.jsx ภายในโฟลเดอร์ components

Cut โค้ดส่วนของ Box จากไฟล์ App.js ไปที่ไฟล์ Box.jsx

โค้ด

import { useRef } from 'react';
import { useLoader, useFrame } from 'react-three-fiber';
import * as THREE from 'three';

const Box = props => {
    const ref = useRef();
    const texture = useLoader(
      THREE.TextureLoader,
      '/wood.jpg'
    );
    useFrame(state => {
      ref.current.rotation.y += 0.01;
      ref.current.rotation.x += 0.01;
    });
  
    const handlePointerDown = e => {
      console.log(e)
      e.object.active = true;
      if (window.activeMesh) {
        scaleDown(window.activeMesh)
        window.activeMesh.active = false;
      }
      window.activeMesh = e.object
    }
  
    const handlePointerEnter = e => {
      e.object.scale.x = 1.5
      e.object.scale.y = 1.5
      e.object.scale.z = 1.5
    }

    const handlePointerLeave = e => {
        if (!e.object.active) {
          scaleDown(e.object)
        }
      }
    
      const scaleDown = object => {
        object.scale.x = 1
        object.scale.y = 1
        object.scale.z = 1
      }
    
      return (
        <mesh
          ref={ref}
          {...props}
          castShadow
          onPointerDown={handlePointerDown}
          onPointerEnter={handlePointerEnter}
          onPointerLeave={handlePointerLeave}
        >
          <boxBufferGeometry args={[1, 1, 1]} />
          <meshPhysicalMaterial
            map={texture}
          />
        </mesh>
      )
    }

    export default Box;


เพิ่มโค้ดนำเข้า Box ที่ไฟล์ App.js

import Box from './components/Box';

สร้างไฟล์ Background.jsx

สร้างไฟล์ Background.jsx ภายในโฟลเดอร์ components

Cut โค้ดส่วนของ Background จากไฟล์ App.js ไปที่ไฟล์ Background.jsx

โค้ด

import { useLoader, useThree } from 'react-three-fiber';
import * as THREE from 'three';

const Background = props => {
    const texture = useLoader(
      THREE.TextureLoader,
      '/autoshop.jpg'
    );
  
    const { gl } = useThree();
  
    const formatted = new THREE.WebGLCubeRenderTarget(
      texture.image.height
    ).fromEquirectangularTexture(gl, texture)
  
    return (
      <primitive
        attach='background'
        object={formatted}
      />
    )
  }

  export default Background;


เพิ่มโค้ดนำเข้า Background ที่ไฟล์ App.js

import Background from './components/Background';

สร้างไฟล์ Floor.jsx

สร้างไฟล์ Floor.jsx ภายในโฟลเดอร์ components

Cut โค้ดส่วนของ Floor จากไฟล์ App.js ไปที่ไฟล์ Floor.jsx

โค้ด


const Floor = props => {
    return (
      <mesh {...props} receiveShadow>
        <boxBufferGeometry args={[20, 1, 10]} />
        <meshPhysicalMaterial
        />
      </mesh>
    )
  }

  export default Floor;



เพิ่มโค้ดนำเข้า Floor ที่ไฟล์ App.js

import Floor from './components/Floor';

สร้างไฟล์ Bulb.jsx

สร้างไฟล์ Bulb.jsx ภายในโฟลเดอร์ components

Cut โค้ดส่วนของ Bulb จากไฟล์ App.js ไปที่ไฟล์ Bulb.jsx

โค้ด

const Bulb = props => {
    return (
      <mesh {...props}>
        <pointLight castShadow />
        <sphereBufferGeometry args={[0.2, 20, 20]} />
        <meshPhongMaterial emissive='yellow' />
      </mesh>
    )
  }

  export default Bulb;


เพิ่มโค้ดนำเข้า Bulb ที่ไฟล์ App.js

import Bulb from './components/Bulb';

สร้างฟังก์ชัน ColorPicker

const ColorPicker = props => {
  return (
    
  )
}


Cut โค้ดจากฟังก์ชัน App ไปที่ฟังก์ชัน ColorPicker


Cut โค้ดจากฟังก์ชัน App ไปที่ฟังก์ชัน ColorPicker

โค้ด

const ColorPicker = props => {
  const handleClick = e => {
    if (!window.activeMesh) return;
    window.activeMesh.material.color = new THREE.Color(e.target.style.background)
  }
  return (
    <div style={{ position: 'absolute', zIndex: 1 }}>
      <div
        onClick={handleClick}
        style={{
          background: 'blue',
          height: 50,
          width: 50
        }}
      ></div>
      <div
        onClick={handleClick}
        style={{
          background: 'yellow',
          height: 50,
          width: 50
        }}
      ></div>
      <div
        onClick={handleClick}
        style={{
          background: 'white',
          height: 50,
          width: 50
        }}
      ></div>
    </div>
  )
}


เพิ่มโค้ดนำเข้าฟังก์ชัน ColorPicker ที่ฟังก์ชัน App

< ColorPicker />

โค้ดไฟล์ App.js

import './App.css';
import {
  Canvas, useFrame
} from 'react-three-fiber';
import { Suspense } from 'react';
import Orbit from './components/Orbit';
import Box from './components/Box';
import Background from './components/Background';
import Floor from './components/Floor';
import Bulb from './components/Bulb';
import * as THREE from 'three'

const ColorPicker = props => {
  const handleClick = e => {
    if (!window.activeMesh) return;
    window.activeMesh.material.color = new THREE.Color(e.target.style.background)
  }
  return (
    <div style={{ position: 'absolute', zIndex: 1 }}>
      <div
        onClick={handleClick}
        style={{
          background: 'blue',
          height: 50,
          width: 50
        }}
      ></div>
      <div
        onClick={handleClick}
        style={{
          background: 'yellow',
          height: 50,
          width: 50
        }}
      ></div>
      <div
        onClick={handleClick}
        style={{
          background: 'white',
          height: 50,
          width: 50
        }}
      ></div>
    </div>
  )
}


function App() {


  return (
    <div style={{ height: '100vh', width: '100vw' }}>
      < ColorPicker />
      <Canvas
        shadowMap
        style={{ background: 'black' }}
        camera={{ position: [7, 7, 7] }}
      >
        <ambientLight intensity={0.2} />
        <Bulb position={[0, 3, 0]} />
        <Orbit />
        <axesHelper args={[5]} />
        <Suspense fallback={null}>
          <Box position={[-4, 1, 0]} />
        </Suspense>
        <Suspense fallback={null}>
          <Box position={[4, 1, 0]} />
        </Suspense>
        <Suspense fallback={null}>
          <Background />
        </Suspense>
        <Floor position={[0, -0.5, 0]} />
      </Canvas>
    </div>
  );
}

export default App;

สร้างไฟล์ ColorPicker.jsx

สร้างไฟล์ ColorPicker.jsx ภายในโฟลเดอร์ components

Cut โค้ดส่วนของฟังก์ชัน ColorPicker จากไฟล์ App.js ไปที่ไฟล์ ColorPicker.jsx

โค้ด ไฟล์ ColorPicker.jsx

import * as THREE from 'three';

const ColorPicker = props => {
    const handleClick = e => {
      if (!window.activeMesh) return;
      window.activeMesh.material.color = new THREE.Color(e.target.style.background)
    }
    return (
      <div style={{ position: 'absolute', zIndex: 1 }}>
        <div
          onClick={handleClick}
          style={{
            background: 'blue',
            height: 50,
            width: 50
          }}
        ></div>
        <div
          onClick={handleClick}
          style={{
            background: 'yellow',
            height: 50,
            width: 50
          }}
        ></div>
        <div
          onClick={handleClick}
          style={{
            background: 'white',
            height: 50,
            width: 50
          }}
        ></div>
      </div>
    )
  }

  export default ColorPicker;
  

เพิ่มโค้ดนำเข้า ColorPicker ที่ไฟล์ App.js

import ColorPicker from './components/ColorPicker';

โค้ด ไฟล์ App.js

import './App.css';
import {
  Canvas, useFrame
} from 'react-three-fiber';
import { Suspense } from 'react';
import Orbit from './components/Orbit';
import Box from './components/Box';
import Background from './components/Background';
import Floor from './components/Floor';
import Bulb from './components/Bulb';
import ColorPicker from './components/ColorPicker';

function App() {


  return (
    <div style={{ height: '100vh', width: '100vw' }}>
      < ColorPicker />
      <Canvas
        shadowMap
        style={{ background: 'black' }}
        camera={{ position: [7, 7, 7] }}
      >
        <ambientLight intensity={0.2} />
        <Bulb position={[0, 3, 0]} />
        <Orbit />
        <axesHelper args={[5]} />
        <Suspense fallback={null}>
          <Box position={[-4, 1, 0]} />
        </Suspense>
        <Suspense fallback={null}>
          <Box position={[4, 1, 0]} />
        </Suspense>
        <Suspense fallback={null}>
          <Background />
        </Suspense>
        <Floor position={[0, -0.5, 0]} />
      </Canvas>
    </div>
  );
}

export default App;

ดูผ่านเว็บไซต์ได้ที่

Leave a Reply

Your email address will not be published. Required fields are marked *