🎞️

Reactで始めるjs + cssアニメーション概論

2021/04/02に公開

はじめに

SHIFTBRAIN さんがデザインされるページってめっちゃいいですよね(まわしものではない)
https://shiftbrain.com/

BtoB の 01 フェーズでプロダクトの管理画面にこんな神のようなクオリティを求められることはないことの方が多いですが、せっかく UI 作るのに携わっているならアニメーションの一つや二つ実装したいですよね
今回、開発中のプロダクトにいくつかアニメーション(簡単なやつだよ、SHIFTBRAIN さんのような神 UI ではないよ)を入れる機会があったので、その時の学びをカンタンなアニメーション概論として記事にしようというお話
React でのアニメーションの第一歩を踏む出すきっかけになれば!

記事のターゲット

  • React でのアニメーションの第一歩を踏み出したい人
  • 小手先のテクニックで表現力に差をつけたいそこのあなた

環境

package.json になります

実際のコード

(筆者が tailwindcss を患っているため tailwindcss が使われています)
https://github.com/nus3/inside-podcast/tree/main/src/components/examples/Example

作ったもの(カクカクしてるのは gif だからです。実物はもっとスマートに動いてます maybe)

transition + js を使ったアニメーション

transition プロパティが指定された css の class を className に持つ要素に対して、hoveronClick などのイベントをトリガに transition で指定したスタイルを変更した class をその要素に付与することでアニメーションさせる方法です

下記の実装例を見てもらえればわかるんですが、シンプルな動きをさせるぶんには結構簡単

css 側でtransition: height 0.2s;でアニメーションつけたいプロパティを指定して、onClick時に className に class 変化させる height を持った class を入れてる

classnames(styles["content1"], {
  [styles.high]: high,
});
実装例
index.module.css
/* postcssの`postcss-nested`使ってscssのようにネストして書けるようにしてやす */
.content1 {
  transition: height 0.2s;
  height: 40px;

  &.high {
    height: 300px;
  }
}
export const Example = (): JSX.Element => {
  const [high, setHigh] = useState<boolean>(false);

  return (
    <div>
      <div className="mb-6">
        <Button
          color="primary"
          label="click me!"
          labelSize="sm"
          onClick={() => setHigh(!high)}
          rounded
        />
      </div>
      <div
        className={classnames(styles["content1"], {
          [styles.high]: high,
        })}
      >
        <Text color="white">content1</Text>
      </div>
    </div>
  );
};

@keyframes + animation プロパティ を使ったアニメーション

transition + js を使ったアニメーションで width やら height やら色変えたりなど(もしくはそれらを組み合わせる)の簡単なアニメーションはできるんですが、この要素を下に動かした後に回転してそこから右に動かしたりもできますよね?とか言われると詰みます

そんなときは@keyframesanimation プロパティを使いましょう

css の@keyframesで要素の0 から 100 の状態を定義します
0 から 100 の状態とは簡単にいうと要素が 0 秒だったら height が 0 で 1 秒だったら・・(以下繰り返し)、最後に 5 秒の時は height を 100px にしようみたいな状態のことです

@keyframesで定義した要素の 0 から 100 の状態をanimation プロパティで使います

/* 0の位置からy軸に200px動くことが書かれてる */
@keyframes moveDown {
  from {
    transform: translateY(0);
  }
  to {
    transform: translateY(200px);
  }
}

.content3 {
  animation-name: moveDown; /* moveDownって名前のkeyframes使うよ */
  animation-duration: 1s; /* 0から100にいくまでの時間は1秒だよ */
  animation-timing-function: ease-in; /* 0から100までどんな感じに動かしたいんだい */
  animation-iteration-count: infinite; /* アニメーションは繰り返すのかい */
  animation-fill-mode: forwards; /* アニメーションが始まる前と終わった後の状態はどうすんだい */
}

こいつが該当します

@keyframesの指定は from to だけでなくパーセント指定もできます

/* アニメーションが0%の時は角度が0度で10%の時は角度が10度で・・・以下略 */
@keyframes swing {
  0% {
    transform: rotate(0deg);
  }
  10% {
    transform: rotate(10deg);
  }
  30% {
    transform: rotate(0deg);
  }
  40% {
    transform: rotate(-10deg);
  }
  50% {
    transform: rotate(0deg);
  }
  60% {
    transform: rotate(5deg);
  }
  70% {
    transform: rotate(0deg);
  }
  80% {
    transform: rotate(-5deg);
  }
  100% {
    transform: rotate(0deg);
  }
}

.content5 {
  animation-name: swing;
  animation-duration: 0.5s;
  animation-timing-function: ease-in-out;
  animation-iteration-count: infinite;
  animation-direction: alternate; /* アニメーションはどの方向で再生するんだい */
}

こいつが該当します

最後に

translateには 2 次元だけでなく 3 次元(translate3dtranslateY)の指定もでき・・・
そう、もうお気づきかもしれませんが、ここまで読んだあなたは CSS アニメーションの深淵の入り口に立っています

Let's enjoy css animation!!

少し昔に作った作品を添えて

GitHubで編集を提案

Discussion