【遊んでみた】framer-motion基本のき

2021.02.15

こんにちは。

サービスグループの金谷です。

今回はframer-motionというライブラリで遊んでみたので紹介したいと思います。

framer-motionとは

Reactで使用できる、オープンソースかつProduction readyなアニメーションライブラリです。

比較的シンプルな記述で書けるのと react-routerとも連動できるのが良いところかと思いました。

(アニメーションのライブラリはたくさんありますが、記述量が多くなるものもあって使うのを諦めてしまうことが私はよくあったので)

Chakra UIのドキュメントにもチラッと出てきますね。

https://chakra-ui.com/guides/integrations/with-framer

環境等

本記事の動作はNodeのバージョンはv15.8.0、framer-motionのバージョンは3.3.0で確認しています。

プロジェクトの作成〜ライブラリのインストールまでは以下のコマンドで実行できます。

npx create-react-app sample
cd sample
npm install framer-motion

また、CodeSandbox等でブラウザ上で簡易的に確認することも可能です。

https://codesandbox.io/s/framer-motion-playground-51ob2?file=/src/index.js

motionコンポーネントを使う

motionコンポーネントとanimateプロパティを使用します。

まずは一番シンプルな使い方をしてみます。

import React from "react";
import ReactDOM from "react-dom";
import { motion } from "framer-motion";

function App() {
  // styleは適当に付けてます
  return (
    <motion.div
      style={{ backgroundColor: "red", width: "30px", height: "30px"}}
      animate={{ 
        x: 100
      }}
    />
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

画面をロードすると赤い四角が右に100px動きます。

CSSで細かな記述をしなくても簡単にアニメーションを実装できましたね。

今度は2秒かけてゆっくり動かしてみます。

transitionを設定してみます。

<motion.div
    style={{ backgroundColor: "red", width: "30px", height: "30px"}}
    animate={{ 
        x: 100
    }}
    transition={{
        duration: 2
    }}
/>

また、animateのプロパティにはキーフレームのような形で配列を渡すことも可能です。

<motion.div
    style={{ backgroundColor: "red", width: "30px", height: "30px"}}
    animate={{ 
        x: [0, 100, 50]
    }}
    transition={{
        duration: 2
    }}
/>

キーフレームで渡された場合、アニメーションの時間はデフォルトでは渡した要素の数で均等に分けられます。

例えば上の例だと1つの動作につき1秒かかります。(0→100、100→50で1秒ずつ)

これをtransitionのtimesというプロパティで上書きすることができます。

<motion.div
    style={{ backgroundColor: "red", width: "30px", height: "30px"}}
    animate={{ 
        x: [0, 100, 50]
    }}
    transition={{
        duration: 2,
        times: [0, 0.2, 1]
    }}
/>

timesに渡す値はanimateに渡した配列と同じ長さで、 かつ0〜1の間で渡す必要があります。

上の例だと0 → 100で 0.2×2 秒、 100 → 50で残りの 0.8×2 秒かけて要素が移動します。

timesに指定できるのは各アニメーションが所用する時間の割合です。

任意のタイミングでアニメーションを発火する

上の例では画面表示時にアニメーションが動いていましたが、大抵の場合は任意のタイミングで発火させたいことが多いかと思います。

そういう場合はuseAnimationというHooksを使えば制御できます。

ボタンを追加し、クリックしたタイミングで発火するようにしてみます。

function App() {
  const controls = useAnimation()

  return (
    <>
      <button onClick={() => controls.start({ x: [0, 100, 50] })}>Start</button>
      <motion.div
        style={{ backgroundColor: "red", width: "30px", height: "30px"}}
        animate={controls}
      />
    </>
  );
}

motionコンポーネントのanimateプロパティにuseAnimationで生成した値 (controls) を渡しておくことで

controlsのメソッド経由で制御することができます。

最後に

今回はframer-motionの基本的な使い方を紹介しました。アニメーションを簡単に実装できて楽しいですね。

公式ドキュメントを読む限りだと上記で紹介した以外にも混み入ったことをすることも可能そうです。

ReactやNext.jsにアニメーションを組み込みたい場合は是非検討してみてください。

公式ドキュメント

https://www.framer.com/api/motion/