Edited at
Three.jsDay 20

Three.js in React.js

More than 1 year has passed since last update.

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を見ればすぐに書けるかと思います。