7. 형태가 바뀌는 이미지패널(2)

훈나무·2022년 7월 6일
0

패널들이 중앙을 바라보게 하기


패널들이 중앙을 바라보게 해보려고 한다. 개인적으로 이 부분이 상당히 어려웠다.

useRef 를 이용해서 패널들 하나하나를 제어해줘야 하는데, useRef 를 배열로 사용하는 방법을 몰라서 찾아봤다.

useRef 로 배열을 컨트롤 하기


가장 먼저 useRef 를 배열로 초기화 시켜준다

const planeRefs = useRef([]);

처음 안 사실이지만 ref 는 item을 불러오는 함수였다…!

따라서 item 을 이용해서 ref에 배열로 되어있는 값에 item 을 하나하나 넣어주면 배열로 된 ref 가 생성된다!!!

{planePositions.map((arr, i) => (
    <mesh ref={(item) => (planeRefs.current[i] = item)} key={i} position={[arr[0], arr[1], arr[2]]}>
      <planeGeometry args={[0.3, 0.3]} />
      <meshBasicMaterial map={textures[i % 5]} side={THREE.DoubleSide} />
    </mesh>
  ))}

중앙을 바라보게 만들기


여기 까지가 힘들었던 부분이고, 이젠 ref 의 배열을 이용해 하나하나 중앙을 바라보게만 해주면 된다.

mesh 는 lookAt 이란 함수를 가지고 있고 이 함수를 이용해서 특정방향을 바라보게 만들 수 있다. 따라서

useEffect(() => {
    const planes = planeRefs.current;
    planes.forEach((plane) => {
      plane.lookAt(0, 0, 0);
    });
  }, [planePositions]);

이렇게 하면 중앙을 바라보는 형태의 구 가 된다!

최종 코드


import { OrbitControls, useTexture } from "@react-three/drei";
import React, { useEffect, useRef, useState } from "react";
import * as THREE from "three";
import img01 from "../images/01.jpg";
import img02 from "../images/02.jpg";
import img03 from "../images/03.jpg";
import img04 from "../images/04.jpg";
import img05 from "../images/05.jpg";

export default function NewThree() {
  const ref = useRef(null);
  const planeRefs = useRef([]);
  const texture01 = useTexture(img01);
  const texture02 = useTexture(img02);
  const texture03 = useTexture(img03);
  const texture04 = useTexture(img04);
  const texture05 = useTexture(img05);
  const textures = [texture01, texture02, texture03, texture04, texture05];

  const [planePositions, setPlanePositions] = useState([]);

  useEffect(() => {
    var tempP = Array.from(ref.current.attributes.position.array);
    var newP = [];
    for (let i = 0; i < tempP.length; i += 3) {
      const temp = [tempP[i], tempP[i + 1], tempP[i + 2]];
      newP.push(temp);
    }
    setPlanePositions(newP);
  }, []);

  useEffect(() => {
    const planes = planeRefs.current;
    planes.forEach((plane) => {
      plane.lookAt(0, 0, 0);
    });
  }, [planePositions]);

  return (
    <>
      <OrbitControls />

      <points>
        <sphereGeometry ref={ref} args={[1, 8, 8]} />
        <meshBasicMaterial transparent />
      </points>

      {planePositions.map((arr, i) => (
        <mesh ref={(item) => (planeRefs.current[i] = item)} key={i} position={[arr[0], arr[1], arr[2]]}>
          <planeGeometry args={[0.3, 0.3]} />
          <meshBasicMaterial map={textures[i % 5]} side={THREE.DoubleSide} />
        </mesh>
      ))}
    </>
  );
}
profile
프론트엔드 개발자 입니다

0개의 댓글

관련 채용 정보