第14回 JavaScript アニメーションによる拡大・縮小（CSS版）

# はじめに
今回は、アニメーションによる要素の拡大・縮小を試したいと思います。
ウェブサイトの広告でよくみかける、広告表示時やクローズ時にアニメーションで拡大・縮小する動作です。
第13回は、`animate`を使用して拡大・縮小を実施しましたが、今回はCSSの`animation-name`で実施したいと思います。
今回はJavaScriptは使用しません。

# 今回実施する内容
CSSの`animation-name`を使用して、要素にマウスカーサーを載せた時に拡大・縮小を実施します。
本当はクリックで実行しようと思いましたが、少し課題があり、それを解決しようとすると今回のテーマから少し外れた内容も記載しなければならないため、`hover`で行うことにしました。課題解決は別記事で記載しようと思います。

以下の４つのパターンを実施します。
- 拡大
- 縮小（縮小後、マウスカーサーを置きなおすと再度元の戻って縮小）
- 水平方向に拡大（拡大後、すぐに初期のサイズに戻る）
- 垂直方向に縮小
![Scale_CSS.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405480/d29360a8-aec5-4e09-f9a1-59eeee744813.gif)

# ソースコード(Git Hub)
https://github.com/Build-Mount/JS_14_css_scale

# 環境
OS: Windows 11 JP (64bit)
Microsoft Edge:バージョン 123.0.2420.65 (公式ビルド) (64 ビット)

# 参考
[animation-name](https://developer.mozilla.org/ja/docs/Web/CSS/animation-name)
[@keyframes](https://developer.mozilla.org/ja/docs/Web/CSS/@keyframes)
[animation-fill-mode](https://developer.mozilla.org/ja/docs/Web/CSS/animation-fill-mode)

# 用語

# アニメーションによる拡大・縮小
## 関数の確認
`animation-name`を使用して、アニメーションを作成したいと思います。

[animation-name](https://developer.mozilla.org/ja/docs/Web/CSS/animation-name)からの抜粋は以下です。
> `animation-name` は CSS のプロパティで、要素に適用されるアニメーションを記述する 1 つまたは複数の `@keyframes` アットルールの名前を指定します。複数の `@keyframe` アットルールをカンマ区切りの文字列で指定します。指定した名前がどの `@keyframe` アットルールにも一致しない場合、プロパティはアニメーションしません。

```CSS:構文
/* 単一のアニメーション */
animation-name: none;
animation-name: test_05;
animation-name: -specific;
animation-name: sliding-vertically;

/* 複数のアニメーション */
animation-name: test1, animation4;
animation-name:
  none,
  -moz-specific,
  sliding;

/* グローバル値 */
animation-name: inherit;
animation-name: initial;
animation-name: revert;
animation-name: revert-layer;
animation-name: unset;
```

ということでこれだとちょっとわかりにくいのですが、例として以下の記載があります。

```CSS:CSS
.box {
  background-color: rebeccapurple;
  border-radius: 10px;
  width: 100px;
  height: 100px;
}

.box:hover {
  animation-name: rotate;
  animation-duration: 0.7s;
}

@keyframes rotate {
  0% {
    transform: rotate(0);
  }
  100% {
    transform: rotate(360deg);
  }
}
```

ということで、`@keyframes`でアニメーションの名前と動作を定義して、`animation-name`に定義した名前を記載すればよいということがわかりました。

[@keyframes](https://developer.mozilla.org/ja/docs/Web/CSS/@keyframes)からの抜粋は以下です。
> `@keyframes` は CSS のアットルールで、アニメーションの流れに沿ったキーフレーム（または中間地点）のスタイルを定義することによって、一連の CSS アニメーションの中間ステップを制御します。これにより、アニメーションの中間ステップをトランジションよりも詳細に制御できます。

```CSS:構文
@keyframes slidein {
  from {
    transform: translateX(0%);
  }

  to {
    transform: translateX(100%);
  }
}
```

> ## 値
>
>`<custom-ident>`
>キーフレームのリストを識別する名前。これは CSS 構文で定義されている識別子に適合する必要があります。
>
>`from`
>アニメーションの始まりである 0% を示します。
>
>`to`
>アニメーションの終わりである 100% を示します。
>
>`<percentage>`
>指定したキーフレームがアニメーションの中で作動する時間を示すパーセント値です。

ということで、`@keyfromes`内にアニメーションの開始は`from`、終了は`to`で記載すればよいことがわかりました。
パーセント表示すれば、その他のタイミングでも設定できることもわかりました。

## ソース
<details><summary>transform_scale_css.html</summary>

```html:transform_scale_js.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Transform scale</title>
    <link rel="stylesheet" href="transform_scale_css.css" type="text/css">
    <script src="transform_scale_css.js" defer></script>
</head>
<body>
    <div id="scale1">拡大はここをクリック</div>
    <div id="scale2">縮小はここをクリック</div>
    <div id="scale3">水平方向拡大はここをクリック</div>
    <div id="scale4">垂直方向縮小はここをクリック</div>
</body>
</html>
```
</details>

<details><summary>transform_scale_css.css</summary>

```css:transform_scale_js.css
#scale1 {
  background-color:yellow;
  position: absolute;
  width: 300px;
  height: 100px;
}

#scale1:hover {
  animation-duration: 1000ms;
  animation-fill-mode: forwards;
  animation-name: scaleIn;
}

@keyframes scaleIn {
  /*キーフレーム*/
  from 
  {transform: scale(1)}
  to
  {transform: scale(2)}
}

#scale2 {
  background-color:red;
  position: absolute;
  width: 300px;
  height: 100px;
  top: 150px;
}

#scale2:hover {
  animation-duration: 1000ms;
  animation-fill-mode: forwards;
  animation-name: scaleOut;
}

@keyframes scaleOut {
  /*キーフレーム*/
  to
  {transform: scale(0.5)}
}

#scale3 {
  background-color:blue;
  position: absolute;
  width: 300px;
  height: 100px;
  top: 300px;
}

#scale3:hover {
  animation-duration: 1000ms;
  animation-name: scaleIn2;
}

@keyframes scaleIn2 {
  /*キーフレーム*/
  from
  {transform: scale(1)}
  to
  {transform: scale(2,1)}  
}

#scale4 {
  background-color:green;
  position: absolute;
  width: 300px;
  height: 100px;
  top: 450px;
}

#scale4:hover {
  animation-duration: 1000ms;
  animation-fill-mode: forwards;
  animation-name: scaleOut2;
}

@keyframes scaleOut2 {
  /*キーフレーム*/
  from
  {transform: scale(1)}
  to
  {transform: scaleY(0.5)}    
}
```
</details>

## ４つの動作の違いと第13回の動作との違いについて
以下の４つのパターンの動作の違いとソースの違いを説明します。
- 拡大
- 縮小（縮小後、マウスカーサーを置きなおすと再度元の戻って縮小）
- 水平方向に拡大（拡大後、すぐに初期のサイズに戻る）
- 垂直方向に縮小

### 拡大のソースと動作

```CSS:CSSの拡大
#scale1:hover {
  animation-duration: 1000ms;
  animation-fill-mode: forwards;
  animation-name: scaleIn;
}

@keyframes scaleIn {
  /*キーフレーム*/
  from 
  {transform: scale(1)}
  to
  {transform: scale(2)}
}
```

```javascript:JavaScriptの拡大
    [
      //キーフレーム
      {transform: 'scale(1)'},
      {transform: 'scale(2)'}
    ],    
    {
      //タイミングオプション
      duration: 1000,
      fill: "forwards"
    }
```

キーフレームは、「キーフレームの開始」と「キーフレームの終了」の`scale(1)`と`scale(2)` を設定し、「キーフレームの開始」は等倍で、「キーフレームの終了」は、２倍拡大します。
`animation-duration`でアニメーション期間を1,000msに設定し、タイミングオプションは、[animation-fill-mode](https://developer.mozilla.org/ja/docs/Web/CSS/animation-fill-mode) を参照して`forwards`を設定し、最後のフレームを保持するようにします。

第13回で作成したJavaScriptのソースも一緒に載せます。
JavaScriptのときはキーフレームは配列で記載しましたが、CSSの`@keyframe`では、`from`と`to`で記載します。


### 縮小（縮小後、クリックしても動作なし）のソースと動作

```CSS: 縮小（縮小後、マウスカーサーを置きなおすと再度元の戻って縮小）
#scale2:hover {
  animation-duration: 1000ms;
  animation-fill-mode: forwards;
  animation-name: scaleOut;
}

@keyframes scaleOut {
  /*キーフレーム*/
  to
  {transform: scale(0.5)}
}
```

```javascript: JavaScriptの縮小（縮小後、クリックしても動作なし）
    [
      {transform: 'scale(0.5)'}
    ],    
    {
      duration: 1000,
      fill: "forwards"
    }
```

キーフレームは、「キーフレームの終了」の`scale(0.5)`を設定し、「キーフレームの開始」は暗黙の等倍で、「キーフレームの終了」は、０．５倍に縮小します。

`animation-duration`でアニメーション期間を1,000msに設定し、タイミングオプションは、[animation-fill-mode](https://developer.mozilla.org/ja/docs/Web/CSS/animation-fill-mode) を参照して`forwards`を設定し、最後のフレームを保持するようにします。

第13回で作成したJavaScriptのソースも一緒に載せます。
JavaScriptでも同じように設定していますが、CSSの`hover`の場合、アニメーション終了後に再度`hover`すると、再度等倍になってアニメーションとなりました。

### 水平方向に拡大（拡大後、すぐに初期のサイズに戻る）のソースと動作

```CSS:水平方向に拡大（拡大後、すぐに初期のサイズに戻る）
#scale3:hover {
  animation-duration: 1000ms;
  animation-name: scaleIn2;
}

@keyframes scaleIn2 {
  /*キーフレーム*/
  from
  {transform: scale(1)}
  to
  {transform: scale(2,1)}  
}
```

```javascript:水平方向に拡大（拡大後、すぐに初期のサイズに戻る）
    [
      //キーフレーム
      {transform: 'scale(1)'},
      {transform: 'scale(2,1)'}
    ],    
    {
      //タイミングオプション
      duration: 1000,
    }
```

キーフレームは、「キーフレームの開始」と「キーフレームの終了」の`scale(1)`と`scale(2,1)` を設定し、「キーフレームの開始」は等倍で、「キーフレームの終了」は、X方向（水平方向）を２倍拡大します。
`scale`の引数2つ目は省略可能で、１つのみの場合は、X軸、Y軸とも同じ値で拡大・縮小しますが、２つ記載する場合、X軸とY軸を別々に設定できます。
`scale(2,1)`とするとX軸は２倍、Y軸は等倍となります。

`animation-duration`でアニメーション期間を1,000msに設定し、タイミングオプションは、[animation-fill-mode](https://developer.mozilla.org/ja/docs/Web/CSS/animation-fill-mode) を設定しないと、アニメーションの最後で「キーフレームの開始」の等倍に戻ります。
アニメーション終了後に再度`hover`すると、水平方向に２倍まで拡大し、その後最初の「キーフレームの開始」の等倍に戻ります。

第13回で作成したJavaScriptのソースも一緒に載せますので参考ください。

### 垂直方向に縮小のソースと動作
```CSS:垂直方向に縮小
#scale4:hover {
  animation-duration: 1000ms;
  animation-fill-mode: forwards;
  animation-name: scaleOut2;
}

@keyframes scaleOut2 {
  /*キーフレーム*/
  from
  {transform: scale(1)}
  to
  {transform: scaleY(0.5)}    
}
```

```javascript:垂直方向に縮小
    [
      //キーフレーム
      {transform: 'scale(1)'},
      {transform: 'scaleY(0.5)'}
    ],    
    {
      //タイミングオプション
      duration: 1000,
      fill: "forwards"
    }
```

キーフレームは、「キーフレームの開始」と「キーフレームの終了」の`scale(1)`と`scaleY(0.5)` を設定し、「キーフレームの開始」は等倍で、「キーフレームの終了」は、Y方向（垂直方向）を０．５倍に縮小します。
`scaleY`はY軸方向のみの拡大・縮小します。

`animation-duration`でアニメーション期間を1,000msに設定し、タイミングオプションは、[animation-fill-mode](https://developer.mozilla.org/ja/docs/Web/CSS/animation-fill-mode) を参照して`forwards`を設定し、最後のフレームを保持するようにします。
アニメーション終了後に再度`hover`すると、等倍に戻って垂直方向に０．５倍まで縮小します。

第13回で作成したJavaScriptのソースも一緒に載せますので参考ください。

# おわりに
第13回のJavaScriptを使用してアニメーションによる拡大・縮小を実施しましたが、第14回では、CSSの`animation-name`と`transform:scale`を使用して、要素の拡大・縮小を実施しました。
同じことが同様にできることは確認できましたが、`animation-fill-mode`、`fill`の動作について、開始キーフレームを設定しないで、`animation-fill-mode`が`forwards`に設定した場合、開始キーフレームに戻るか否かの動作に違いがありました。
JavaScriptの場合：元に戻らない。
CSSの場合：元に戻る。