【CSS】【JavaScript】フェードイン・フェードアウト

# 目的

画像や文字が徐々に出現したり消えたりする、フェードイン・フェードアウト機能をCSSとJavaScriptでなるべく簡単に実装します。

# 実装

![ghorst.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629925/6a587c28-3de9-c690-eb12-c56bec9750ab.gif)

```index.html
<div class="img">
  <img id="ghorst" class="ghorst" src="obake.png">
</div>

<button id="hide-btn">いないいな〜い</button>
<button id="appear-btn">ばぁ！</button>
```

```stylesheet.css
/* アニメーションの設定 */
.ghorst {
  transition: opacity 3s; /* opacity要素(不透明度)の変更を3秒間かけて行う */
}
```

```script.js
// 各要素を取得
const ghorst = document.getElementById('ghorst');
const hideBtn = document.getElementById('hide-btn');
const appearBtn = document.getElementById('appear-btn');

// 画像を透明にする処理
const ghorstHide = () => {
  ghorst.style.opacity = 0; // 画像要素のopacityプロパティの値を0(透明)にする
};

// 画像を不透明にする処理
const ghorstAppear = () => {
  ghorst.style.opacity = 1; // 画像要素のopacityプロパティの値を1(不透明)にする
};

// 各ボタン要素がクリックされた時の処理を指定
hideBtn.addEventListener('click', ghorstHide);
appearBtn.addEventListener('click', ghorstAppear);
```

## 使用　プロパティ・メソッド

| CSSプロパティ　| 意味 | 参考サイト |
|:----------:|:---:|:-------:|
| [opacity](#opacity) | 要素の不透明度を設定 | [MDN Web Docs](https://developer.mozilla.org/ja/docs/Web/CSS/opacity) |
| [transition](#transition) | 要素のアニメーションを定義する | [MDN Web Docs](https://developer.mozilla.org/ja/docs/Web/CSS/transition-duration) |

| JavaScriptプロパティ・メソッド | 意味 | 参考サイト |
|:---------------:|:---:|:--------:|
| getElementById() | HTMLのidから要素を取得する | [MDN Web Docs](https://developer.mozilla.org/ja/docs/Web/API/Document/getElementById) |
| [style](#style) | 要素のスタイルを変更する | [MDN Web Docs](https://developer.mozilla.org/ja/docs/Web/API/HTMLElement/style) |
| addEventListener() | 要素にイベントが起こったときに実行される処理を指定 | [MDN Web Docs](https://developer.mozilla.org/ja/docs/Web/API/EventTarget/addEventListener) |

## 解説

CSSプロパティの`opacity`で不透明度が指定できるため、`transition`で`opacity`の値が変更されたときの変化アニメーションを定義します。
JavaScriptで`opacity`の値を変更することで、`transition`で定義されたアニメーションが実行されます。

### opacity

要素の不透明度を指定します。

0〜1の間で指定し、
0: 透明
1: 不透明
になっています。例えば、`opacity: 0.5;`と指定すると、その要素は半透明になります。

### transition

要素の値が変更された際の、アニメーションの動きを定義します。`transiton`は、以下のの4つのプロパティを一括で指定できます(半角区切り)。
複数指定する場合はカンマ`,`で区切ります。
値の変更方法は、JavaScriptの`classList`や`style`、CSSの`:hover`など。

| プロパティ | 意味 | 参考サイト |
|:-------:|:----:|:-------:|
| [transition-property](#transition-property) | 効果を適用するプロパティの指定<br>(propaty: プロパティ) | [MDN Web Docs](https://developer.mozilla.org/ja/docs/Web/CSS/transition-property) |
| [transition-duration](#transition-duration) | アニメーションが完了するまでの時間を指定<br>(duration: 持続・継続・間隔） | [MDN Web Docs](https://developer.mozilla.org/ja/docs/Web/CSS/transition-duration) |
| [transition-timing-function](#transition-timing-function) | 変化の速度とタイミングを指定<br>(timing function: タイミング機能・時間調整機能) | [MDN Web Docs](https://developer.mozilla.org/ja/docs/Web/CSS/transition-timing-function)
| [transition-delay](#transition-delay) | アニメーションが始まるまでの時間を指定<br>(delay: 遅延・先延ばし) | [MDN Web Docs](https://developer.mozilla.org/ja/docs/Web/CSS/transition-delay) |

```css
.class {
  transition: 対象プロパティ 完了までの時間 変化の速度 開始までの時間;
}

/* 複数指定 */
.class {
  transition:
    プロパティA 完了時間 変化速度 開始時間,
    プロパティB 完了時間 変化速度 開始時間,
    プロパティC 完了時間 変化速度 開始時間;
}
```

#### transition-property

変化させるCSSのプロパティを指定します。
フェードイン・フェードアウトでは、`opacity`を指定しています。
指定を`all`とすることで、全てのプロパティを同時に指定することもできます。

#### transition-duration

アニメーションが完了するまでの時間の指定ができます。
`s`: 秒
`ms`: ミリ秒
の二つで指定できます。
今回は`3s`とすることで、3秒でフェードイン・フェードアウトをしています。

#### transition-timing-function

アニメーションの変化の速度を指定できます。

| 値 | 意味 |
|:--:|:---:|
| [ease](#ease) | 滑らか(初期値) |
| [linear](#linear) | 一定速度 |
| [ease-in](#ease-in) | ゆっくり始まる |
| [ease-out](#ease-out) | ゆっくり終わる |
| [ease-in-out](#ease-in-out) | ゆっくり始まり、ゆっくり終わる |
| [cubic-bezier](#cubic-bezier) | 3次ベジェ曲線を数値で指定(x1, x2, y1, y2) |

##### ease

![car-ease.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629925/fb33ccf0-28b6-5a4a-0153-9503debe861b.gif)

```css
.car {
  transition: 4s ease; /* 4秒で滑らかに */
}
```

##### linear

![car-linear.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629925/5099ada8-df58-64a1-780d-d81a234085ea.gif)

```css
.car {
  transition: 4s linear; /* 4秒間一定速度で */
}
```

##### ease-in

![car-ease-in.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629925/2039ddd1-2678-9216-c155-0a471e7c6d77.gif)

```css
.car {
  transition: 4s ease-in; /* 4秒でゆっくり始まる */
}
```

##### ease-out

![car-ease-out.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629925/4639451a-369a-ea6e-6867-cc94a30d5f11.gif)

```css
.car {
  transition: 4s ease-out; /* 4秒でゆっくり終わる */
}
```

##### ease-in-out

![car-ease-in-out.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629925/b7656f6a-ba89-419b-6076-1b1de075c7e9.gif)

```css
.car {
  transition: 4s ease-in-out; /* 4秒でゆっくり始まりゆっくり終わる */
}
```
##### cubic-bezier

![car-cubic-bezier.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629925/cd6744e7-c535-141c-eaea-49219c4f1133.gif)

```css
.car {
  transition: 4s cubic-bezier(0, 0.76, 1, 0.23); /* 4秒で真ん中ゆっくり */
}
```
参考サイト: [Cubic Bezier(ジェネレータ)](https://cubic-bezier.com/#.17,.67,.83,.67)

#### transition-delay

アニメーションの開始時間を指定できます。
`s`: 秒
`ms`: ミリ秒
の二つで指定できます。

![car-delay.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629925/e1fe78e6-847f-b4b4-2c6c-b10297ec0a35.gif)

```css
.car {
  transition: 4s 3s; /* スタートを押してから3秒後に4秒間で移動 */
}
```

### style

JavaScriptでCSSプロパティの値を取得・変更する際に使用します。

今回は、

```javascript
const ghorst = document.getElementById('ghorst');
```
で、画像の要素を取得し、

```javascript
ghorst.style.opacity = 0;
```
とすることで、　`opacity`の値を変更しています。
この変更に`transition`プロパティが反応し、アニメーションが実行されます。

## 注意点

簡単にフェードイン・フェードアウトを実装できる`transition`ですが、比較的新しい技術のため、古いブラウザ(IE9など)では動作しません。
対応ブラウザは[DOM Web Docs(transition)](https://developer.mozilla.org/ja/docs/Web/CSS/transition#browser_compatibility)や、[Can I use (transition?)](https://caniuse.com/?search=transition)などを参照してください。

# プラス

さらに動きをつけてみました。

![ghorst2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629925/e55392d3-e214-8e78-a71c-a6137f2d5d88.gif)

```html
<!-- HTMLは変更ありません -->
<div class="img">
  <img id="ghorst" class="ghorst" src="obake.png">
</div>

<button id="hide-btn">いないいな〜い</button>
<button id="appear-btn">ばぁ！</button>
```

```css
/* レイアウトが崩れないように画像の場所取り */
.img {
  width: 300px;
  height: 320px;
}

/* 画像に高さ・幅を指定 */
.ghorst {
  width: 300px;
  height: 320px;
  transition: all 3s; /* width, height, opacityをまとめて指定するため、プロパティを　all　に変更 */
}

/* フェードアウトするときの値 */
.hide {
  width: 0;
  height: 0;
  opacity: 0;
}

/* フェードインするときの値 */
.appear {
  width: 300px;
  height: 320px;
  opacity: 1;
}
```

```javascript
const ghorst = document.getElementById('ghorst');
const hideBtn = document.getElementById('hide-btn');
const appear = document.getElementById('appear-btn');

// クラスを付け替えることで、まとめて値を変更
const ghorstHide = () => {
  ghorst.classList.remove('appear');
  ghorst.classList.add('hide');
};

const ghorstAppear = () => {
  ghorst.classList.remove('hide');
  ghorst.classList.add('appear');
};

hideBtn.addEventListener('click', ghorstHide);
appear.addEventListener('click', ghorstAppear);
```

### classList

要素のクラスを操作することができるプロパティです。

`remove()`メソッドを使用することで、クラスを削除し、`add()`メソッドでクラスを追加しています。

[MDN Web Docs](https://developer.mozilla.org/ja/docs/Web/API/Element/classList)

<br>
<br>

ご覧いただき、ありがとうございました。