react-three-fiberを使ってSVGをバラバラに動かしてみる

DESIGNER

REACT THREE FIBER

react-three-fiberは、Three.jsのためのReactレンダラー。動的なシーングラフを簡単に作れる優れものです。

今回はこのreact-three-fiberを使って、シーングラフを再利用可能なコンポーネントに分離し、アニメーションをつける方法をご紹介します。

react-three-fiberを使ってSVGをバラバラに動かしてみる

Reactとは、Facebookが開発したJavaScriptライブラリです。頭に浮かんだアイデアを、レゴブロックのようにコンポーネントに変身させられるのが特徴です。

しかしそんなReactにも、コンポーネントの処理方法を指示するための調整プログラムが必要ですあ。調整プログラムには、ARやVRなどさまざまなプラットフォームにリーチするものがありますが、その中でもreact-three-fiberはコンポーネントをThree.jsのシーングラフに変換してくれるものとなります。

1. シーンを設定する

react-three-fiberの「Canvas」コンポーネントが、Three.jsへのポータルです。ここに入るものはすべて、Three.js固有のオブジェクトになります。

以下で作成しているのは、ライトがついたレスポンシブキャンバスです。

function App() {
  return (
    <Canvas>
      <ambientLight intensity={0.5} />
      <spotLight intensity={0.5} position={[300, 300, 4000]} />
    </Canvas>
  )
}

2. SVGをそれぞれ図形に変換する

今回のゴールはSVGパスを抽出し、それぞれ別個にアニメーションを加えることです。そのためあまりレイヤーが多くない、シンプルなイラストを使用するのが良いでしょう。

react-three-fiber-2
Three.jsのSVGLoderを使って、SVGをジオメトリに変換しましょう。

以下は、図形と色を含むオブジェクトのネストした配列です。Z座標を指定するためのindexも収集します。

const svgResource = new Promise(resolve =>
  new loader().load(url, shapes =>
    resolve(
      flatten(
        shapes.map((group, index) =>
          group.toShapes(true).map(shape => ({ shape, color: group.color, index }))
        )
      )
    )
  )
)

次に、図形をレンダリングする「Shape」コンポーネントを定義します。それぞれの図形は、indexによって50ユニットにオフセットされています。

function Shape({ shape, position, color, opacity, index }) {
  return (
    <mesh position={[0, 0, index * 50]}>
      <meshPhongMaterial attach="material" color={color} />
      <shapeBufferGeometry attach="geometry" args={[shape]} />
    </mesh>
  )
}

次に必要なのが、作成した図形をマッピングするコンポーネントです。先ほど作ったリソースがロードされたら、ローカルコンポーネントのstateに書き込み、作成しておいた「Shape」コンポーネントに各図形を転送します。

function Scene() {
  const [shapes, set] = useState([])
  useEffect(() => void svgResource.then(set), [])
  return (
    <group>
      {shapes.map(item => <Shape key={item.shape.uuid} {...item} />)}
    </group>
  )
}

これで、キャンバスにSVGが表示されます。

3. アニメーションをつける

Three.jsにアニメーションをつけたい場合は、GSAPなどのツールを使うのがおすすめです。

今回はアニメーションを調整するためのシステムが必要ですが、これを構築するのは簡単ではありません。しかし今回はReactコンポーネントをレンダリングしているため、アニメーションやトランジションツールなど、エコシステムに存在するものはほとんどすべて使用できるのです。今回はreact-springを使います。

このステップで行うべきことは、図形をtransition-groupに変換することです。transition-groupはstateの変化を監視し、安全に削除できるようになるまで古いstateを保持して遷移させるのに役立ちます。

react-springの場合、これを「useTransition」と呼びます。元のデータ(ここでは図形)、データセットの変更を識別するためのkey、そしてstateが追加・削除・または変更された際に、useTransitionは何を実行するかを定義できるのです。

そして、すべてを網羅しているのが以下です。追加された図形は、sceneに軌道を残すかたちでトランジションします。また削除されると、トランジションアウトします。

const transitions = useTransition(shapes, item => item.shape.uuid, {
  from: { position: [0, 50, -200], opacity: 0 },
  enter: { position: [0, 0, 0], opacity: 1 },
  leave: { position: [0, -50, 10], opacity: 0 },
})

return (
  <group>
    {transitions.map(({ item, key, props }) => <Shape key={key} {...item} {...props} />)}
  </group>
)

useTransitionは、生成されたkey、元のデータ(ここでは図形)、アニメーション化されたプロパティを含むオブジェクトの、それぞれの配列を作成します。すべてをShapeコンポーネントに展開したら、あとはアニメーション化した値を受け取るためにそのコンポーネントを準備するだけです。

react-springは、「animated」と呼ばれるヘルパーと、「a」と呼ばれるショートカットをエクスポートします。これを使ってエレメントを拡張すると、これらのプロパティが処理できるようになります。基本的に、divがあれば「a.div」になり、meshがあれば「a.mesh」になります。

おわりに

今回の記事を読んでみて、「react-three-fiberreact-springについてもっと詳しく知りたい!」と思った方もいるのではないでしょうか。そんなときは、ぜひ上記のそれぞれのリンクをクリックして、説明を読んでみてください。英語ではありますが、一番詳しく解説されているはずです。

オリジナルデモに必要なコードはこちらから確認できます。

(原文:Paul Henschel 翻訳:Asuka Nakajima)

 

こちらもおすすめ!▼

SHARE

RELATED

  • お問い合わせ
  • お問い合わせ
  • お問い合わせ