728x90
문제
Next@13.2.0버전에 @react-three/fiber^8.15.11, @react-three/drei^9.88.17, three^0.158.0을 적용하고,
다음 코드와 같이 텍스트를 Canvas에 감싸면 렌더링 되겠지 했더니 다음과 같은 에러가 난다.
<main style={{ width: '100vw', height: '100vh' }}>
<Canvas
camera={{
position: [10000, 10000, 10000],
rotation: [-0.5, 0, 0],
far: 100000,
}}
>
<color attach="background" args={['#000']} />
<ambientLight color={'#fff'} intensity={5} />
<OrbitControls />
이렇게 텍스트 넣으려고 했는데, 오류남
</Canvas>
{children}
</main>
Text is not allowed in the R3F tree! This could be stray whitespace or characters.
해결방법1
다음과 같은 Text컴포넌트를 만들어서, json으로 된 폰트를 지정하여 텍스트 렌더링하는 방법
// Import necessary dependencies
import { useEffect, useMemo } from 'react';
import * as THREE from 'three';
import { useLoader, useThree } from '@react-three/fiber';
import { TextGeometry } from 'three/examples/jsm/geometries/TextGeometry';
import { FontLoader } from 'three/examples/jsm/loaders/FontLoader';
// Create a Text component
const Text = ({ children, ...props }: any) => {
const { size = 1, color = '#000000', ...restProps } = props;
const { camera } = useThree();
// Load a font (you can replace 'path/to/your/font.json' with the actual path)
const font = useLoader(FontLoader, '/fonts/KimjungchulGothic.json');
// Calculate size based on camera position
const calculatedSize = useMemo(() => {
const distance = camera.position.distanceTo(new THREE.Vector3(0, 0, 0));
return (size * distance) / 1000; // Adjust the divisor as needed
}, [size, camera.position]);
// Create text geometry
const geometry = useMemo(() => {
const textGeometry = new TextGeometry(children, {
font,
size: calculatedSize,
height: 0.1, // Adjust as needed
curveSegments: 12,
bevelEnabled: false,
});
textGeometry.center();
return textGeometry;
}, [children, font, calculatedSize]);
return (
<mesh {...restProps} geometry={geometry}>
<meshStandardMaterial color={color} />
</mesh>
);
};
export default Text;
나는 위와 같은 방식으로 하면, 원래 했던 코드들을 저런식으로 모두 바꿔야해서 다음 방법을 사용함
해결방법2
css로 position: absolute를 지정하여 상단으로 끌어올리는것
'use client';
import React from 'react';
import styled from 'styled-components';
export const AbsolDiv = styled.div`
display: flex;
position: absolute;
flex-direction: row;
top: 100px;
left: 50%;
transform: translate(-50%, 0%);
`;
나는 styled component를 사용해서 common이라고 만들고 그안에 저렇게 정의한 후, 다음과같이 사용했다.
'use client';
import { AbsolDiv } from '../../_components/common';
import PageHeader from '../../_components/pageHeader';
import PortfolioMain from './portfolioMain';
import PortfolioMini from './portfolioMini';
export default function Page() {
return (
<AbsolDiv className="projects">
<main>
<PageHeader titleBg="Projects">
My <span className="point">Projects</span>
</PageHeader>
<section>
<PortfolioMain />
<PortfolioMini />
</section>
</main>
</AbsolDiv>
);
}
결과 완성본 두둥!!
'2. FrontEnd > Three.js' 카테고리의 다른 글
[Three.js] R3F(React Three Fiber) (1) | 2023.11.21 |
---|---|
Three.js (01. 정의, 구조 및 개념) (0) | 2023.05.23 |