LoginSignup
0
1

More than 3 years have passed since last update.

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

Last updated at Posted at 2020-04-17

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"
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 }
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

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

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1