【React】keyframeを利用して流体UIを手軽に作成する

# 背景
モダンなサイトを見ていると、
波のように揺れる流体UIを見る事があります。
このようなおしゃれなUIを作れるようになりたいと思い調べてみました。
本記事では、以下のgif画像内の3つの流体UIの作成について紹介します。

# 作成する物
- 左：グラテーションがかかった丸めのUI
- 真ん中：左のUIにぼかしを加えたもの
- 右：徐々にぼかしがかかる丸めの画像が見えるUI

![liquiUisample.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/6d5ae860-1e6f-0661-d073-6101bd538509.gif)

# 環境
- React：18.2.0
- Vite：5.0.8

# コード
HTML要素にcssの`keyframe`でアニメーションを付けていきます。
まずは以下のようにHTML要素を作成します。
流体UIを3つ作成する予定なので、HTML要素も同じ数準備します。

```react:App.jsx
// 外部ファイルのインポート
import './App.css'

function App() {
  return (
    <>
      <div className="main-container">
        <div className="liquid-ui-left"></div>
        <div className="liquid-ui-center"></div>
        <div className="liquid-ui-right"></div>
      </div>
    </>
  )
}

export default App;
```

続いてcssを作成していきます。
`App.css`の1ファイルしかないですが、
長々と書くと見にくいのでいくつかに分けて記載していきます。

`main-container`クラスについては、
次のように要素が横並びになるようにフレックスボックスを使用しています。

```css:App.css
body {
  padding: 0;
  margin: 0;
}

.main-container {
  display: flex;
  flex-direction: row;
  justify-content: space-around;
  align-items: center;
  width: 100vw;
  height: 100vh;
  background-color: aliceblue;
}
```

次に3つの要素を作成していきます。
それぞれのクラスにおいて、`animation`プロパティで繰り返しアニメーションを指定しています。

- ### liquid-ui-leftクラス
  `linear-gradient`でグラテーションをかけて色を付けています。

- ### liquid-ui-centerクラス
  `liquid-ui-leftクラス`に`filter`プロパティでぼかしを加えています。

- ### liquid-ui-right
  `background`プロパティで背景に画像（今回は三日月）をしています。
  
```css:App.css
.liquid-ui-left {
  width: 300px;
  height: 300px;
  background: linear-gradient(90deg, #00c6ff, #0072ff);
  border-radius: 27% 69% 40% 46%;
  animation: move 10s linear infinite;
}

.liquid-ui-center {
  width: 300px;
  height: 300px;
  background: linear-gradient(90deg, #00c6ff, #0072ff);
  border-radius: 20% 60% 30% 50%;
  filter: blur(20px);
  animation: move2 12s linear infinite;
}

.liquid-ui-right {
  width: 300px;
  height: 300px;
  background: url("./assets/moon_and_star3.png");
  background-size: cover;
  background-position: center center;
  border-radius: 20% 60% 30% 50%;
  filter: blur(0);
  animation: move3 10s linear infinite;
}
```

続いて、`keyframe`についてです。

- ### moveアニメーション
  一番左のUIに指定しています。
  0~100%の間をいくつかの段階に分けて、`border-radius`プロパティの値を
段階ごとに少々違いのあるものにしながら指定しています。


- ### move2アニメーション
　真ん中のUIで使用しています。
　値は違いますがやっている事は`move`と同じ感じです。

- ### move3アニメーション
　`border-radius`プロパティの指定に加えて、
　`filter`プロパティで徐々にぼかしがかかり、
　ぼかしが消えていくアニメーションを付けています。

```css:App.css
@keyframes move {
  0% {
    border-radius: 27% 69% 40% 46%;
  }

  16.666% {
    border-radius: 35% 65% 45% 50%;
  }

  33.333% {
    border-radius: 45% 55% 50% 50%;
  }

  50% {
    border-radius: 55% 50% 55% 50%;
  }

  66.666% {
    border-radius: 65% 45% 60% 40%;
  }

  83.333% {
    border-radius: 32% 69% 40% 46%;
  }

  100% {
    border-radius: 27% 55% 35% 40%;
  }
}

@keyframes move2 {
  0% {
    border-radius: 20% 60% 30% 50%;
  }

  20% {
    border-radius: 60% 40% 70% 30%;
  }

  40% {
    border-radius: 20% 60% 30% 50%;
  }

  60% {
    border-radius: 60% 40% 70% 30%;
  }

  80% {
    border-radius: 20% 60% 30% 50%;
  }

  100% {
    border-radius: 20% 60% 30% 50%;
  }
}

@keyframes move3 {
  0% {
    border-radius: 25% 60% 40% 50%;
    filter: blur(0);
  }

  16.666% {
    border-radius: 50% 50% 50% 50%;
    filter: blur(0);
  }

  33.333% {
    border-radius: 65% 35% 55% 45%;
    filter: blur(5px);
  }

  50% {
    border-radius: 50% 50% 50% 50%;
    filter: blur(10px);
  }

  66.666% {
    border-radius: 25% 60% 40% 50%;
    filter: blur(10px);
  }

  83.333% {
    border-radius: 15% 65% 25% 60%;
    filter: blur(5px);
  }

  100% {
    border-radius: 25% 60% 40% 50%;
    filter: blur(0px);
  }
}
```
`border-radius`、`filter`のプロパティの値を変えれば、
好みの流体UIアニメーションに変える事ができます。

# 実行結果
`npm run dev`で実際に動かして確認すると以下のように
揺れ動く流体UIが作成できました。

![liquiUisample.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/26b81a18-39b7-0178-886b-a31256d0915e.gif)

# 参考
https://qiita.com/duka/items/0c6b5182b64237f83bc9