반응형
카엔입니다
카엔
카엔입니다
전체 방문자
오늘
어제
  • 분류 전체보기 (98)
    • 프론트엔드 (74)
      • JavaScript (22)
      • CSS (2)
      • React (21)
      • Next.js (12)
      • 블록체인 (2)
    • 에러 모음 (11)
    • Git (5)
    • 백엔드 (1)
      • GraphQL (1)
    • AWS (2)
    • CS (1)
    • 코딩테스트 (1)
    • 개발 이야기 (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • ipc 통신
  • useCallback
  • git 덮어쓰기
  • 모바일 파란 박스
  • nextron ipc
  • error
  • Cloudfront
  • 자릿수 채우기
  • 웹상동작과정
  • useMemo
  • ec2
  • ChatGPT
  • Next.js
  • git
  • nextron
  • 자바스크립트 이진수 변환
  • DOUBLE CHECK CONFIGURATION Please double check that you have setup a PAID OpenAI API Account. You can read more here: https://docs.agpt.co/setup/#getting-an-api-key
  • 이벤트루프
  • 구글 스프레드시트 API
  • unoptimized error

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
카엔입니다

카엔

리액트, Next.js에서 three.js GLFT 모델 적용하기
프론트엔드/JavaScript

리액트, Next.js에서 three.js GLFT 모델 적용하기

2023. 4. 25. 13:55

https://www.kaen.site/

위 화면처럼 포트폴리오 메인 화면에 사용될 Three.js를 적용하는 방법에 대해 공유하려합니다

자세한 내용보다는 해당 코드를 복붙해서 사용할 수 있는 정도로만 간단하게 공유할 예정입니다

 

리액트 세팅

우선 리액트 코드입니다

const loadingHandler = (toggle: boolean) => {
    setLoading(toggle);
};

useEffect(() => {
    three(gltfName, loadingHandler);
}, []);

return (
    <HomeSection mobile={isMobile}>
        <canvas id={gltfName}></canvas>

        <h1>SUNGHUN LEE</h1>
        <div></div>
        <span>Frontend Developer</span>

        <Link href="/about" className="wrapper">
            <a>About me</a>
        </Link>
    </HomeSection>
)

three라는 함수를 통해 gltfName과 loadingHandler를 전달해주면

gltf 폴더안에 해당하는 gltfName 모델을 canvas에 넣어주게됩니다

 

useEffect를 통해 재렌더링 될때 모델을 다시 불러오도록 설정해주면

기본적인 리액트 세팅이 끝나게 됩니다

 

three.js 세팅

import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import Stats from "three/examples/jsm/libs/stats.module";

export const three = (name: string, loadingHandler: any) => {
	loadingHandler(true);

	let mouseX = 0,
		mouseY = 0;
	let windowHalfX = window.innerWidth / 2;
	let windowHalfY = window.innerHeight / 2;

	const scene = new THREE.Scene();
	// scene.add(new THREE.AxesHelper(5));

	const webGL: any = {
		canvas: document.querySelector(`#${name}`),
		antialias: true,
		alpha: true,
	};

	// RENDERER
	const renderer = new THREE.WebGLRenderer(webGL);
	// renderer.physicallyCorrectLights = true;

	renderer.shadowMap.enabled = true;
	renderer.outputEncoding = THREE.sRGBEncoding;
	renderer.setSize(window.innerWidth, window.innerHeight);

	// LIGHT
	// const light = new THREE.SpotLight();
	const light = new THREE.DirectionalLight(0xffffff, 0.5);
	// const light = new THREE.AmbientLight(0x404040);
	light.position.set(4, 4, 5);
	scene.add(light);

	// const light1 = new THREE.AmbientLight(0xffffff, 0.2);
	// scene.add(light1);

	// CAMERA
	const camera = new THREE.PerspectiveCamera(
		15,
		window.innerWidth / window.innerHeight,
		0.1,
		1000
	);
	camera.position.x = 5;
	camera.position.y = 10;
	camera.position.z = 10;

	// let helper = new THREE.CameraHelper(light.shadow.camera);
	// scene.add(helper);

	// scene.background = new THREE.Color(color.defaultBg);

	// document.body.appendChild(renderer.domElement);

	const controls = new OrbitControls(camera, renderer.domElement);
	controls.enableDamping = false;

	// LOADER
	const loader = new GLTFLoader();
	loader.load(
		`/gltf/${name}/scene.gltf`,
		function (gltf: any) {
			const model = gltf.scene;

			model.position.setX(4);
			model.position.setY(0);
			model.position.setX(0);

			gltf.scene.traverse(function (child: any) {
				if ((child as THREE.Mesh).isMesh) {
					const m = child as THREE.Mesh;
					m.receiveShadow = true;
					m.castShadow = true;
				}
				if ((child as THREE.Light).isLight) {
					const l = child as THREE.Light;
					l.castShadow = true;
					l.shadow.bias = -0.003;
					l.shadow.mapSize.width = 2048;
					l.shadow.mapSize.height = 2048;
				}
			});

			function animate() {
				requestAnimationFrame(animate);

				gltf.scene.rotation.z += 0.0008;
				gltf.scene.rotation.y -= 0.0008;
				// gltf.scene.rotation.x -= 0.001;

				controls.update();

				render();

				stats.update();
			}

			renderer.domElement.addEventListener(
				"mousemove",
				onDocumentMouseMove,
				false
			);

			animate();

			function onDocumentMouseMove(event: any) {
				mouseX = event.clientX - windowHalfX;
				mouseY = event.clientY - windowHalfY;
			}

			scene.add(gltf.scene);
		},
		(xhr: any) => {
			console.log((xhr.loaded / xhr.total) * 100 + "% loaded");
		},
		(error: any) => {
			console.error(error);
		}
	);

	// () => {
	// 	window.addEventListener("resize", onWindowResize, false);
	// 	function onWindowResize() {
	// 		camera.aspect = window.innerWidth / window.innerHeight;
	// 		camera.updateProjectionMatrix();
	// 		renderer.setSize(window.innerWidth, window.innerHeight);
	// 		render();
	// 	}
	// };

	const stats = Stats();
	// document.body.appendChild(stats.dom);

	function render() {
		renderer.render(scene, camera);

		loadingHandler(false);
	}
};

 

그대로 복사해서 쓰실분 이 부분만 수정해서 사용하시면 됩니다

 

카메라

camera.position.x = 5;
camera.position.y = 10;
camera.position.z = 10;

알맞게 숫자를 바꿔가면서 카메라 위치를 잡으시면 됩니다

카메라 각도에 따라 물체를 보는 시점이 바뀌게 됩니다

 

회전속도

function animate() {
        requestAnimationFrame(animate);

        gltf.scene.rotation.z += 0.0008;
        gltf.scene.rotation.y -= 0.0008;
        // gltf.scene.rotation.x -= 0.001;
}

물체가 회전하는 속도를 조절하게 됩니다

저작자표시 (새창열림)

'프론트엔드 > JavaScript' 카테고리의 다른 글

구글 스프레드시트 API 조회하기 | Node.js  (0) 2023.05.15
자바스크립트 이진수 자릿수만큼 0 채우기  (0) 2023.04.28
자바스크립트 이벤트 루프가 뭘까  (0) 2023.02.16
GET과 POST의 차이는 뭘까  (0) 2023.02.15
클로저란 것은 뭘까  (0) 2023.02.14
    '프론트엔드/JavaScript' 카테고리의 다른 글
    • 구글 스프레드시트 API 조회하기 | Node.js
    • 자바스크립트 이진수 자릿수만큼 0 채우기
    • 자바스크립트 이벤트 루프가 뭘까
    • GET과 POST의 차이는 뭘까
    카엔입니다
    카엔입니다
    https://www.kaen.site/

    티스토리툴바