1.実装したいもの
textGeometryを使って、3Dの文字を作りたい
2.ディレクトリ構成&コード
ディレクトリ構成を関係ありそうなところだけ書いておきます。
root/
├ build/
├ public/
└ src/
├ components/
│ └ Text.js
├ resources/
│ └ bold.blob
├ App.js
└ index.js
src/resources/bold.blobは、react-three-fiberのココにあります。
https://github.com/react-spring/react-three-fiber/tree/master/examples/src/resources/fonts
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-router-dom": "^5.1.2",
"react-scripts": "3.4.1",
"react-three-fiber": "4.0.7",
"three": "^0.115.0"
import * as THREE from 'three'
import React, { Suspense, useRef, useMemo } from 'react'
import { Canvas, useLoader, useFrame, useThree, extend } from 'react-three-fiber'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import bold from '../resources/bold.blob'
extend({ OrbitControls })
export function Controls() {
const ref = useRef()
const { camera, gl } = useThree()
useFrame(() => ref.current.update())
return <orbitControls ref={ref} args={[camera, gl.domElement]} enableDamping dampingFactor={0.1} rotateSpeed={0.5} />
}
function Text({ st, size = 1, ...props }) {
const font = useLoader(THREE.FontLoader, bold)
const config = useMemo(
() => ({
font,
size: 30,
height: 30,
curveSegments: 32,
bevelEnabled: true,
bevelThickness: 6,
bevelSize: 2.5,
bevelOffset: 0,
bevelSegments: 8,
}),
[font]
)
const mesh = useRef([st])
return (
<mesh
ref={mesh}
scale={[0.1 * size, 0.1 * size, 0.1]}
{...props}>
<textGeometry attach="geometry" args={[st, config]} />
<meshNormalMaterial attach="material" />
</mesh>
)
}
function BoldText() {
const ref = useRef()
useFrame(({ clock }) => {
const time = clock.getElapsedTime()
ref.current.position.y = Math.sin(time) * 3
})
return (
<group ref={ref}>
<Text position={[-8, 4, 0]} st="3D" size={1.3}/>
<Text position={[0, 4, 0]} st="TEXT" size={1.3}/>
<Text position={[-8, 0, 0]} st="WITH" />
<Text position={[ 4, 0, 0]} st="R3F" />
</group>
)
}
const TextGeo = () => {
return (
<div style={{ background: 'aqua' }}>
<ul>
<li>ドラッグしてカーソルを動かすと、カメラの位置を動かせます。</li>
<li>マウスのホイールでカメラの位置を遠ざけたり、近づけたり出来ます。</li>
</ul>
<Canvas
camera={{ position: [0, 5, 20] }}
style={{ height:'800px' }}
>
<ambientLight intensity={2} />
<Suspense fallback={null}>
<BoldText />
</Suspense>
<Controls />
</Canvas>
</div>
)
}
export { TextGeo }
import React from 'react'
import { BrowserRouter, Route, Switch, Link } from 'react-router-dom'
//import './css/index.css'
import { Home } from './components/Home'
import { TextGeo } from './components/Text'
const App = () => {
return (
<BrowserRouter>
<div>{document.title}</div>
<Switch>
<Route exact path='/'><Home /></Route>
<Route path='/1'><TextGeo /></Route>
</Switch>
<Link to='/'>ホーム画面へ</Link>
<Link to='/1'>動く3D文字</Link>
</BrowserRouter>
)
}
export default App;
3.参考にしたもの
4.感想
FontLoader , textGeometryとかはどう使うのかなーと思って、やってみました。
まあ、react-three-fiberのサンプルにあったやつをFontLoader関連の部分だけに削っていじっただけなんですけどねw
それと、blob形式じゃなくてjson形式の文字データ?を読み込みたかったのでやってみたんですけど、なぜかエラーが出て無理でした。
5.僕の関連記事
TextureLoader
・https://qiita.com/drafts/56d211a47d139e424e5b/
shaderMaterila
・https://qiita.com/kageyama0/items/1e50f9966d1afad57329