グラデーションのアニメーションの背景をReactで設定するには（SVG、Canvas、動画、CSS比較）

明けましておめでとうございます。

# 目標

目標としてはこのようなグラデーションのアニメーションをWebの背景に設定するということです。
![bg_gradient_animation (2).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188304/9e69040c-dd03-0524-466c-1e52ef676124.gif)
※QiitaはSVGをアップロードできないためGIFで表示


# グラデーションのアニメーションの背景を表示する手段


1. SVG
2. Canvas
3. 動画
4. CSS Animation

これらが考えられます。メリットデメリットについて比較します。

## SVG

### メリット
- 画質が劣化しない
- ファイルサイズが小さい

### デメリット
- 複雑なアニメーションになると、自分で書くのが面倒
- SVGアニメーションを扱えるGUIソフトウェアが限られている


## Canvas

### メリット
- 画質が劣化しない

### デメリット
- 複雑なアニメーションになると、自分で書くのが面倒

## 動画

### メリット
- 動画を扱えるGUIソフトウェアが多いため、アニメーションを制作する上で色々な手段がある

### デメリット
- ファイルサイズが大きくなりローディングに時間がかかる

## CSS Animation

### メリット
- 画質が劣化しない

### デメリット
- 複雑なアニメーションになると、自分で書くのが面倒


# 試した手段

## Adobe After Effectでアニメーションを作成

After Effectで4色グラデーションというエフェクトを用いて、アニメーションを制作しました。

Bodymovinというプラクインを使えば、SVGにエクスポートできるとのことだったが、
エフェクトには対応していないため、SVGにアニメーションが反映されなかったです。

動画として以下のようなコードでWebの背景に設定しました。
しかし、読み込みが遅く最善の方法ではなかったです。

※ Chakra UIを使用しています。
```jsx
<Box
  height="100vh"
  pos="relative"
  overflow="hidden"
  backgroundColor="hsla(0,0%,0%,0)"
>
  <Box
    as="video"
    playsInline
    autoPlay
    muted
    loop
    pos="absolute"
    minW="100%"
    minH="100vh"
    w="auto"
    h="auto"
    objectFit="cover"
  >
    <source src="background.mp4" type="video/mp4" />
  </Box>
</Box>
```

## Adobe Animateでアニメーションを作成

Adobe Animateでアニメーションを作成し、Canvasにエクスポートしました。

Reactで使用するには、[react-adobe-animate](https://github.com/bibixx/react-adobe-animate)を使うとスムーズです。

※ Chakra UIを使用しています。
```jsx
<Box
  height="100vh"
  pos="relative"
  overflow="hidden"
  backgroundColor="hsla(0,0%,0%,0)"
>
    <Box w="100vw"
        pos="absolute"
        minW="100%"
        minH="100vh"
        w="auto"
        h="auto"
        objectFit="cover">
        <AnimateCC
            style={{width: "100vw",height: "100vh",display: "flex",
                justifyContent: "center",
                alignItems: "center"
              }}
            canvasStyle={{height: "100vh", width: "auto"}}
            animationName="< animation name >"
            getAnimationObject={ getAnimationObject }
        />
    </Box>
</Box>
```

`AnimateCC`というコンポーネントの`canvasStyle`は、私が追加した要素です！canvasにスタイルが当てられないと中央にフィットして背景を表示させられなかったため、作りました。

該当するプルリク↓

https://github.com/bibixx/react-adobe-animate/pull/77

https://github.com/bibixx/react-adobe-animate/pull/76

## SVGでアニメーションを作成

[SVGator](https://www.svgator.com)というブラウザツールを用いた。

簡単にSVGのアニメーションを作ることができます。

### SVGatorでアニメーションを作る注意点

SVGエクスポートのオプションでJavaScriptかCSSで動かすかという項目があります。
JavaScriptで動かす場合、`imgタグ`で読み込む、CSSの`background`で設定するとき、動きません。
`imgタグ`で読み込む、CSSの`background`で設定するときは、CSSで動かしましょう。

そしてCSSで動かす時の注意点があります。曲がったパスに沿って動かす機能はブラウザで対応していないことがあります。(なぜなら、CSSの`offset-distance`プロパティが対応していない)
特にiPhoneで動かないため、避けた方がいいでしょう。

私は、円状に動かしたい時、正多角形の辺のような動きをさせて対応しました。カクカクならず直線で動いてるとはバレにくいです。

https://www.svgator.com/help/technical-issues/browser-support

### SVG背景をReactで設定

`backgroungImage`に埋め込むため、`raw-loader`を使用しています。

backgroundImageで設定することで、普通の写真同様、背景の設定ができます。

```jsx
import BgAnimation from "../public/bg-animation.svg";


~~省略~~

<Box
  height="100vh"
  bgColor="hsla(0,0%,0%,0)"
  bgImage={`url("data:image/svg+xml;base64,${Buffer.from(
    BgAnimation
  ).toString("base64")}")`}
  bgRepeat="no-repeat"
  bgSize="cover"
  bgPosition="center"
></Box>
```
※Chakra UIを使用しています。

# 結果

動画、Canvas、SVGなど試しましたが、SVGが最適だと思います。
SVGで実現できる限りはSVGに頼ります。
CSSでSVGを動かすときは主要なブラウザに対応しているかに確認しましょう。


# SVGグラデーションアニメーターの開発

SVGでグラデーションのアニメーションを動かした経験を生かして、SVGグラデーションアニメーターを作りました。
色を変えるだけで、簡単にSVGグラデーションアニメーションを作れます。
ぜひ、ご利用ください！

https://technologies.anharu.me/tools/gradient-svg

作れるアニメーション例↓
![wave-gradiation (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188304/12970cc0-fbf1-f0cb-d568-1279b0ba9e9a.gif)