【ブラシ】画像をアニメーションで切り替えたい！オシャレに！【塗りつぶし】

[画像をアニメーションで切り替えたい！オシャレに！](https://qiita.com/drooooopp/items/5d7ef537461ae3f23c3b) の詳細記事となります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116793/46471a48-7c59-f1e4-80f0-0bff94564228.gif" width="300">

今回は【ブラシで塗りつぶし】のアニメーションです。
実際の挙動は以下のようになります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116793/b2c408e2-eea1-4ba3-1af8-0cc519ed68ba.gif" width="300">


CSSの `mask-image` を利用しての実装になります。
早速実装です！

## 1. HTMLの追加

```{html}
<div class="animate js-animate" data-is-animated="false">
  <div class="animate_item" data-animate-number="1">
    <img src="image_1-1.jpg">
  </div>
  <div class="animate_item" data-animate-number="2">
    <img src="image_1-2.jpg">
  </div>
</div>
```

まずHTMLで、 `切り替え前の画像` `切り替え後の画像` を用意します。
それぞれ、上なのか下なのかがわかるようにdata属性を割り当てその外側にも状態管理用のdata属性を記載します。

**image_1-1**
![image_1-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116793/51fb059b-673f-6cec-e9c4-116b7152dae1.jpeg)

**image_1-2**
![image_1-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116793/cbe4a0f6-f8e8-8b36-dedd-193d57b6d1ed.jpeg)


## 2. CSSの追加

```{css}
.animate {
  position: relative;
}

.animate_item {
  position: absolute;
}

[data-is-animated="true"] [data-animate-number="1"] img,
[data-is-animated="false"] [data-animate-number="2"] img {
  position: relative;
  z-index: 2;
  -webkit-mask-image: url("sprite.png");
  -webkit-mask-size: auto 100%;
  -webkit-mask-repeat: repeat;
  -webkit-mask-position: auto 0;
  mask-image: url("sprite.png");
  mask-size: auto 100%;
  mask-repeat: repeat;
  mask-position: auto 0;
  animation: sprite-animation 1.2s steps(15);
  animation-fill-mode: forwards;
}

[data-is-animated="true"] [data-animate-number="2"] img,
[data-is-animated="false"] [data-animate-number="1"] img {
  position: relative;
  z-index: 1;
  animation: inherit;
}
```

CSSではそれぞれの `切り替え前の画像` `切り替え後の画像` に対して、表示するときのアニメーションなどの記載をします。

### (sprite.png... どこから出てきました...?)

冒頭でお伝えした
>CSSの `mask-image` を利用しての実装になります。

ということで、画像で画像にマスクをかける必要があります。

- マスクをかけるためにマスク用の画像が必要
- マスク用の画像は、懐かしのcssスプライトの要領で、アニメーションのコマ分連結した画像になる
- 1コマのタテヨコ比などはマスクをかける側の画像と合わせる必要がある

上記を踏まえ、今回用意したマスク画像は以下です。

![sprite.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116793/fed52620-71fe-e8ea-a266-348c9ae324dd.png)

フリーのブラシ素材を利用して作成するか、てっとり早いのは概要をデザイナーさんに伝えて、作成してもらうと良いと思います。

### (sprite-animation... どこに書いてあります...?)
そうなりますよね。
アニメーションキーフレームは以下の、JavaScriptに記載しています。


## 3. JavaScriptの追加

```{JavaScript}
const el = document.querySelector('.js-animate')
const itemWidth = el.offsetWidth
const spriteWidth = itemWidth * 15
const styleTag = document.createElement('style')
styleTag.textContent = `
  .animate_item {
    width: ${itemWidth}px;
  }
  .animate_item img {
    width: ${itemWidth}px;
  }
  @keyframes sprite-animation {
    0% {
      mask-position: 0 0;
      -webkit-mask-position: 0 0;
    }
    100% {
      mask-position: -${spriteWidth}px 0;
      -webkit-mask-position: -${spriteWidth}px 0;
    }
  }
`

document
  .getElementsByTagName('head')[0]
  .insertAdjacentElement('beforeend', styleTag)
```

CSS側で指定していたアニメーションキーフレーム(sprite-animation)は、JavaScriptから指定しています。
アニメーションの最終位置を指定するのに、画像の横幅を指定する必要がありますが、多くの場合画像の横幅は固定ではなく可変だと思うので、JavaScript側で指定するようにしてあげます。

## 完成！

<img src="https://user-images.githubusercontent.com/44596341/150675807-237f015c-dbec-4efa-a18c-781bee6d5aca.gif" width="200">

画像を可愛い猫にしてみました。
こんなにオシャレに！（猫かわいい）画像切り替えが！（猫がかわE...）簡単に！（猫かわいいなぁ）できちゃいました！（猫がかわ...）

あとは必要に応じてCSSでのレイアウトや、JavaScriptでのタイミングを調整すれば色々な見せ方ができると思います。

## 最後に
[mask-position | Can I use...](https://caniuse.com/mdn-css_properties_mask-position)
実案件で利用できるかは上記を踏まえてご利用ください。

### その他のアニメーション切り替え記事はこちら
[【斜め】画像をアニメーションで切り替えたい！オシャレに！【グリッド】](https://qiita.com/drooooopp/items/daae7613269d41d612b7)
[【スライド】画像をアニメーションで切り替えたい！オシャレに！【縦 横 斜め】](https://qiita.com/drooooopp/items/94eb6f8e1e5009ab75d9)
[【フリップ】画像をアニメーションで切り替えたい！オシャレに！【くるっと】](https://qiita.com/drooooopp/items/586813b06591af3ef37b)