35
35

More than 5 years have passed since last update.

Three.js in React.js

Last updated at Posted at 2016-12-25

react-three-rendererを使うことで、Three.jsのオブジェクトをJSXの中でコンポーネントとして記述することができます。

Example (w/redux)

scene, camera, meshなどThree.jsのオブジェクトがcomponentとして提供されていて、通常のReactComponent同様にsetStateで描画が更新されます。アニメーション処理はonAnimate内に記述します。

example.jsx
import React from 'react';
import React3 from 'react-three-renderer';
import { connect } from 'react-redux'
import * as THREE from 'three';
import { fetchTexture } from '../actions/texture';

const pi = Math.PI;
const rad = pi / 180;
const width = window.innerWidth;
const height = window.innerHeight;

class Example extends React.Component {
  state = {
    dirZ: -1,
    dirRad: rad,
    planePosition: new THREE.Vector3(0, 0, 500),
    planeRotation: new THREE.Euler(0, 0, 0)
  };

  cameraPosition = new THREE.Vector3(0, 100, 500);
  lightPosition = new THREE.Vector3(0, 100, 30);

  componentDidMount() {
    this.props.fetchPhotosWithTexture();
  }

  onAnimate() {
    this.setState({
      planePosition: new THREE.Vector3(
        this.state.planePosition.x,
        this.state.planePosition.y,
        this.state.planePosition.z + this.state.dirZ
      ),
      planeRotation: new THREE.Euler(
        this.state.planeRotation.x + this.state.dirRad,
        this.state.planeRotation.y,
        this.state.planeRotation.z + this.state.dirRad
      )
    });
  }

  render() {
    return (
      <React3
        mainCamera="camera"
        width={width}
        height={height}
        clearColor={0x000000}
        pixelRatio={window.devicePixelRatio}
        onAnimate={this.onAnimate.bind(this)}
      >
        <scene>
          <directionalLight position={this.lightPosition} />
          <ambientLight color={0xaaaaaa} />
          <perspectiveCamera
            name="camera"
            fov={45}
            aspect={width / height}
            near={1}
            far={2000}
            position={this.cameraPosition}
          />
          <gridHelper size={200} step={50} />
          <axisHelper size={1000} />

          {this.props.texture ?
            <mesh
              position={this.state.planePosition}
              rotation={this.state.planeRotation}
            >
              <planeGeometry
                width={this.props.texture.image.width / 2}
                height={this.props.texture.image.height / 2}
              />
              <meshLambertMaterial
                map={this.props.texture}
                side={THREE.DoubleSide}
              />
            </mesh>
          : null}
        </scene>
      </React3>
    );
  }
}

export default connect(
  state => ({ texture: state.texture }),
  { fetchTexture }
)(Example)

雑なsample

Debug

便利なことにReact Developer Toolsも通常のReact.jsと同じように使うことができます。
(さすがにprops, stateはReadOnlyになっていてこちらから動的に変えることはできないようですが)

スクリーンショット 2016-12-25 22.48.43.png

所感

私はReact.js製のアプリケーション内にThree.jsのコンテンツを表示するために使いましたが、Three.jsのオブジェクトの構造をより明示的に記述できるのは良いですね。React.js, Three.jsどちらも触ったことがあればAPI Documentationを見ればすぐに書けるかと思います。

35
35
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
35
35