LoginSignup
17
11

More than 1 year has passed since last update.

VRMファイルの中身を表示するWebサイトそ作る過程でReact 内で Three.js を扱ったので、使用した場合の知見などについて共有します。
※ ここでは react-three-renderer などのライブラリを使わず、素の ReactThree.js を使う方法を紹介します。

また、今回、「VRMファイルの中身を表示するWebサイト」のソースコードはこちらに公開しています。

NodeVrmMetaRipper

作成したデモページはこちらです。

デモページ

作ったものについて

人型の3DModelファイルであるVRMファイルの中にあるMeta情報(Boneとかアニメーションとか)を抽出して表示するWebAPIを作成してみました。
VRMファイルの中身はJSONになっているのでその情報を抽出することができます。

参考

使用した技術

WebAPI

Demo Page

React

ReacttはUIのパーツ(構成部品)を作るためのライブラリです。
FacebookがOSSとして公開しています。
Typescriptで開発することもできます。(今回紹介しているものはTypescriptにて記述しています。)
Reactのセットアップや導入については React公式 ページにまとまっていますので今回は省略します。

Reactの中でthree.jsを使う

three.jsのインストール

まずはthree.jsをインストールします。

yarn add three

最新の three.js にはTypescriptで開発するために必要なものが入っているので @types/three のインストールをする必要はありません。

three.jsで何か表示してみる

Reactにて three.js を使って最小限のソースコードで何かしら表示させる方法は以下のようになります

import React from 'react';
import { WebGLRenderer, Scene, PerspectiveCamera } from 'three';

class App extends React.Component {
  onCanvasLoaded = (canvas: HTMLCanvasElement) => {
    if (!canvas) {
      return;
    }
    const renderer = new WebGLRenderer({ canvas: canvas, antialias: true });
    const scene = new Scene();
    // new THREE.PerspectiveCamera(視野角, アスペクト比, near, far)
    const camera = new PerspectiveCamera(45, canvas.clientWidth / canvas.clientHeight, 1, 2000);
    renderer.render(scene, camera);
  };

  render():
    | React.ReactElement<any, string | React.JSXElementConstructor<any>>
    | string
    | number
    | {}
    | React.ReactNodeArray
    | React.ReactPortal
    | boolean
    | null
    | undefined {
    return (
      <div>
        <canvas ref={this.onCanvasLoaded} />
      </div>
    );
  }
}

export default App;

React のJSX内ではcanvasを指定することができますので、React.Component を継承したClass内で描画処理を行っている render メソッドに canvas タグを指定します。このとき canvas タグの中の ref プロパティはcanvas が描画された直後に呼ばれるものです。この ref プロパティの中で取得できる canvas (Typescriptだと canvas: HTMLCanvasElement)を three.jsWebGLRenderer に指定してあげれば、指定した canvas に描画されます。
あとは three.js の描画に必要な Sceneカメラ (今回は場合はPerspectiveCamera) を指定することで表示されます。

three.jsで色々と動かせる状態にする

上記の表示した内容は静止画になります。
three.js で動画のようにいろいろ動かしてみたくなると思います。
その場合の実装方法は以下のようになります。

import React from 'react';
import { WebGLRenderer, Scene, PerspectiveCamera } from 'three';

class App extends React.Component {
  private scene: Scene | null = null;
  private camera: PerspectiveCamera | null = null;
  private renderer: WebGLRenderer | null = null;

  constructor(props: any) {
    super(props);
    this.animate = this.animate.bind(this);
  }

  onCanvasLoaded = (canvas: HTMLCanvasElement) => {
    if (!canvas) {
      return;
    }
    this.renderer = new WebGLRenderer({ canvas: canvas, antialias: true });
    this.scene = new Scene();
    // new THREE.PerspectiveCamera(視野角, アスペクト比, near, far)
    this.camera = new PerspectiveCamera(45, canvas.clientWidth / canvas.clientHeight, 1, 2000);
    this.animate()
  };

  animate() {
    window.requestAnimationFrame(this.animate);
    if (this.renderer && this.scene && this.camera) {
      this.renderer.render(this.scene, this.camera);
    }
  }

  render():
    | React.ReactElement<any, string | React.JSXElementConstructor<any>>
    | string
    | number
    | {}
    | React.ReactNodeArray
    | React.ReactPortal
    | boolean
    | null
    | undefined {
    return (
      <div>
        <canvas ref={this.onCanvasLoaded} />
      </div>
    );
  }
}

export default App;

window.requestAnimationFrame(this.animate) ここで自身の function を指定することで、指定した function が繰り返し実行されるようになります。
これにより three.js 内でアニメーションするようになります。
しかし、React にて描画に影響を与える場合は事前に bind しないとエラーが発生します。そのため、constructor にて this.animate = this.animate.bind(this); と指定することで、連続しての描画を実現しています。

あとは色々と表示させるためにScene に追加したり、DirectionalLight で光を当てたり、positionscale を変更させたり、各種 three.js の処理を作成していくことで、Reactthree.js が共存した物を作ることができます。

まとめ

React 内で three.js を使う場合についての紹介と実際に作成したものについて紹介しました。
React への three.js の導入は割とすんなり導入できるのではないかと思います。
ReactGatsbyJS など人気のプロジェクト(ツール)に使われていることも多くあるので、これらを使いつつ、three.js を導入する場合の参考となればと思います。

17
11
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
17
11