react-three-fiberで3Dの文字を表示して動かしてみた。

# 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

```package.json(一部)
    "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"
```

```react:src/components/Text.js
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 }
```

```react:src/components/App.js
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;
```

完成品！
![Peek 2020-04-17 17-36.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428938/03725bf3-947d-8c34-ab0f-d940854e73f0.gif)

# 3.参考にしたもの
https://github.com/react-spring/react-three-fiber/blob/master/examples/src/demos/Font.js


# 4.感想
FontLoader , textGeometryとかはどう使うのかなーと思って、やってみました。
まあ、react-three-fiberのサンプルにあったやつをFontLoader関連の部分だけに削っていじっただけなんですけどねｗ
それと、blob形式じゃなくてjson形式の文字データ？を読み込みたかったのでやってみたんですけど、なぜかエラーが出て無理でした。

# 5.僕の関連記事
TextureLoader
・https://qiita.com/drafts/56d211a47d139e424e5b/

shaderMaterila
・https://qiita.com/kageyama0/items/1e50f9966d1afad57329