homehome

React Simple Animateでアニメーション処理

Published

Reactコンポーネントをアニメーションさせるというのは若干面倒な点もあるのですが、React Simple Animateは名前の通り超簡単にアニメーションを実現させてくれるライブラリです。

提供されているコンポーネントは、Animate, AnimateKeyframes, AnimateGroupの3つ。これらの使い方は、公式のサンプルを眺めれば瞬時に理解できるほどシンプルです。

ただし、v2とv3でprops名が異なることがあるため注意が必要です。この記事ではv3.3.0を対象にしています。

Animate

AnimateはスタイルをA⇔Bでアニメーションさせます。最低限必要なpropsは下記の3つです。

<Animate
  play={false}
  start={{ opacity: 1, filter: 'blur(0)' }}
  end={{ opacity: 0, filter: 'blur(10px)' }}
>
  <MyComponent />
</Animate>

startが初期スタイル、end が変更後のスタイルです。playtrueになったときにアニメーションしますが、最初からtrueだとコンポーネントロード後にアニメーションします。

その他の主なオプションは以下です。

  • duration - アニメーションの長さ
  • deplay - アニメーション開始までの時間指定
  • complete - アニメーション完了後のスタイル指定
  • easeType - Easingタイプの指定
  • onComplete - アニメーション完了後のコールバック

例:文字のフェードアニメーション(抜粋)

import React from 'react';
import { Animate } from 'react-simple-animate';

const MyComponent = ({ play }) => (
  <>
    <Animate
      play={play}
      start={{ opacity:1, filter: 'blur(0)' }}
      end={{ opacity: 0, filter: 'blur(10px)' }}
    >
      <p>Hello World!</p>
    </Animate>
  </>
);

export default MyComponent;

単にテキストをフェードイン/フェードアウトさせています。playは親コンポーネントからtrue/falseを渡して、スイッチさせているだけです。

AnimationKeyframes

AnimationKeyframesは、CSSキーフレームアニメーションそのものです。

必須propsはplaykeyframesです。

<AnimateKeyframes
    play={true}
    pause={false}
    iterationCount="infinite"
    direction="alternate"
    duration={5}
    keyframes={[
      'transform: rotateX(0) rotateY(0) rotateZ(0)',
      'transform: rotateX(360deg) rotateY(360deg) rotateZ(360deg)',
    ]}
>
	<MyComponents />
</AnimateKeyframes>

keyframesはデフォルトでは等間隔にアニメーションを行います。上記は下記と同等です。パーセント(中割り)は自由に指定可能で、2つに限る必要はありません。

keyframes={[
  // 0%
  { 0: 'transform: rotateX(0) rotateY(0) rotateZ(0)' },
  // 100%
  { 100: 'transform: rotateX(360deg) rotateY(360deg) rotateZ(360deg)' }
]}

残りのオプションは以下です。

  • pause - アニメーションの一時停止オプション(trueで一時停止)
  • iterationCount - 繰り返し回数
  • direction - アニメーション再生の向き(animation-directionに該当)
  • duration - アニメーションする秒数
  • easeType - Easingタイプの指定
  • fillMode - 実行前後にどうスタイルを適用させるか(animation-fill-modeに該当)

例は、スターウォーズのOPAnimationKeyframesで部分再現したものです👉プレビュー

例:AnimateKeyframesの抜粋全文

import React from 'react';
import { AnimateKeyframes } from 'react-simple-animate';

const MyComponent = () => (
  <div className="starwars-demo">
    <AnimateKeyframes
      play={true}
      iterationCount="infinite"
      direction="normal"
      duration="5"
      easeType="ease-out"
      keyframes={[
        { 0: "opacity: 0; transform: scale(1.5) translateY(-0.75em)" },
        { 20: "opacity: 1" },
        { 89: "opacity: 1; transform: scale(1)" },
        { 100: "opacity: 0; transform: translateZ(-1000em)" }
      ]}
    >
      <img src="//cssanimation.rocks/demo/starwars/images/star.svg" />
    </AnimateKeyframes>
    <AnimateKeyframes
      play={true}
      iterationCount="infinite"
      direction="normal"
      duration="5"
      easeType="ease-out"
      keyframes={[
        { 0: "opacity: 0; transform: scale(1.5) translateY(0.5em)" },
        { 20: "opacity: 1" },
        { 90: "opacity: 1; transform: scale(1)" },
        { 100: "opacity: 0; transform: translateZ(-1000em)" }
      ]}
    >
      <img src="//cssanimation.rocks/demo/starwars/images/wars.svg" />
    </AnimateKeyframes>
  </div>
);

export default MyComponent;

keyframs内では、transformでスケールとtransformZでZ軸への移動をしています。遠近感のトリックはCSSです。

.starwars-demo {
  transform-style: preserve3d;
  perspective: 800px;
}

利用しているのは、transform-styleperspectiveです。前者で要素を3D空間に配置し、後者でそのZ軸(奥行き)の距離を設定しています。

AnimationGroup(Animation Sequences)

AnimationGroupは順番通りの(シーケンス)アニメーションを実現します。複数の要素を規定の順番でアニメーションさせたい場合は、これを利用します。

<AnimateGroup play={true}>
	<Animate start={{ opacity: 0 }} end={{ opacity: 1 }} sequenceIndex={0}>
  	first
  </Animate>
  <Animate start={{ opacity: 0 }} end={{ opacity: 1 }} sequenceIndex={1}>
  	second
  </Animate>
  <Animate start={{ opacity: 0 }} end={{ opacity: 1 }} sequenceIndex={2}>
  	third
  </Animate>
</AnimateGroup>

AnimateAnimateGroupでラップすることで、順番にアニメーションさせられます。順番はsequenceIndexに指定した順です。sequenceIdsequencesで同様のことも行えるようですが、こちらは公式ドキュメントに沿うと自分の環境では動作しなかったため、様子見です。

<AnimateGroup play sequences={[
    { sequenceId: 'first', ...props},
    { sequenceId: 'second', ...props },
    { sequenceId: 'third', ...props }
]}>
    <Animate sequenceId="first">first</Animate>
    <Animate sequenceId="second">second</Animate>
    <Animate sequenceId="third">third</Animate>
</AnimateGroup>

基本はAnimateコンポーネントのため、特に難しいことはないはずです。

尚、ここまでの例はすべてインラインスタイルで定義してきましたが、公式にあるようにHookでの記述も可能です(React@^16.7以上が必要)。