JavaScriptによるスライドショー作成 その2

こんにちは。
前回からの続きになります。https://qiita.com/amanomunt/items/432cbf9c5a654695a720

## nextボタンとprevボタンの処理
まずは次に進む [ next ] ボタンです。
ボタンにはhtml上でIDをつけてあるので、それを取得してクリックイベントを追加します。

イベントの処理は、
1.現在のカレントクラスを外す（removeCurremtClass関数呼び出し）
2.カレントナンバーを一つ追加（次に進む）
3.それに合わせてメイン画像を差し替え（setMainImage関数呼び出し）

```JavaScript:JavaScript
  const next = document.getElementById('next');
  next.addEventListener('click', () => {
    removeCurremtClass(); // カレントクラスを外す
    currentNum++; // カレントナンバーに1足す（更新）
    addCurremtClass(); // 更新したインデックスにカレントクラスを追加する
    setMainImage(images[currentNum]); // メイン画像をきりかえる
  });
```

ただしこのままだと、サムネイルの最後までいったうえでnextボタンを押すとエラーになるので、そのあたりを修正します。
ついでに、最後まで行ったら次は先頭に戻るように修正しましょう。


```JavaScript:JavaScript
  const next = document.getElementById('next');
  next.addEventListener('click', () => {
    removeCurremtClass();
    currentNum++;
    if (currentNum === images.length) { // currentNumがlength=配列要素数と同じになったら
      currentNum = 0; // 0に戻す
    }
    addCurremtClass();
    setMainImage(images[currentNum]);
  });
```
ここでif文の条件`currentNum === images.length`にちょっとした解説です。
images配列のlengthは8つなのですが、`currentNum`は0から7の8つとなります。

したがって、配列8番目を選択してる時の`currentNum`は7ということになりますね。
そのため、最後の要素の時にnextを押すと`currentNum`が8になり、`images.length`と同じになる。
そうなったら0番目に戻ろうね、という処理になります。

同様に [ prev ] ボタンの処理を書きます。
異なる点はcurrentNumを減らすことと、if文です。

```JavaScript:JavaScript
  const prev = document.getElementById('prev');
  next.addEventListener('click', () => {
    removeCurremtClass();
    currentNum--; // カレントナンバーを1引く（更新）
    if (currentNum < 0) { // currentNumが0より小さくなったら
      currentNum = images.length - 1; // 最後の要素に飛ばす
    }
    addCurremtClass();
    setMainImage(images[currentNum]);
  });
```
今度は0より小さくなったら要素の最後に飛ばす処理にします。
上記のように、8番目の要素は`currentNum`としては7になるので、`images.length`の8から1引くので、`currentNum = images.length - 1;`となるんですね。


## Playボタンでスライドショーを再生できるようにする
まずはplay要素を取得し、イベントを追加しましょう。

処理も`playSlideShow`という関数を作りそこにまとめます。



```JavaScript:JavaScript
  const play = document.getElementById('play'); // play要素取得
  play.addEventListener('click', () => {
    playSlideShow(); // スライドショー開始関数呼び出し
  });
```

`playSlideShow`関数を書いていきましょう。
スライドショーとは要は、自動的に次へ行くのだから、nextの処理を自動化させれば良いでしょう。
一定時間ごとに**nextをclick**することを繰り返せば良いので、`setTimeout`関数を使います。ここでは確認のために、少し早く300ミリ秒ごとにとします。

```JavaScript:JavaScript
  function playSlideShow() {
    setTimeout(() => { // 一定時間でループ
      next.click(); // nextボタンクリック時と同じ動作
      playSlideShow(); // 再度呼び出し
    }, 300);
  }
```
次に、スライドショーを再生したら停止させるための[ stop ]ボタンの処理を書きます。

一番最初に書いたhtmlの中でもともと[ stop ]ボタンを用意してあり、`hidden`クラスという`display:none;`属性をつけて隠してあります。
それと[ play ]ボタンに`hidden`クラスを使って、再生中、停止中で表示・非表示を切り替えます。


まず[ pause ]ボタンを取得します。
そして[ play ]ボタンのクリックイベント内で、各ボタンの`hiddden`クラスを操作します。


```JavaScript:JavaScript
  const play = document.getElementById('play');
  const pause = document.getElementById('pause'); // pause要素取得

  play.addEventListener('click', () => { // playボタンが押されたら
    play.classList.add('hidden'); // playボタンを非表示に
    pause.classList.remove('hidden'); // pauseボタンを表示させる
    playSlideShow();
  });

```

次に[ pause ]ボタンの処理を書きます。

## Pauseボタンでスライドショーを停止させる

まずはひとつずつ、[ pause ]ボタンを押されたときの表示・非表示クラスの切り替え処理を書きます。


```JavaScript:JavaScript
  pause.addEventListener('click', () => { // pauseボタンが押されたら
    pause.classList.add('hidden'); // playボタンを表示させる
    play.classList.remove('hidden'); // pauseボタンを非表示に
  });

```


スライドショーを停止させるには`setTimeout`を停止させる`clearTimeout`を使います。
ただし`clearTimeout`は`setTimeout`の返り値が必要になるので、先程書いた`setTimeout`の箇所で変数宣言しましょう。

```JavaScript:JavaScript
  let timeouId; // setTimeout の返り値が必要になるので宣言

  function playSlideShow() {
    timeouId = setTimeout(() => { // timeouIdにsetTimeoutの返り値を入れる
      next.click();
      playSlideShow();
    }, 300);
  }
```

```JavaScript:JavaScript
  pause.addEventListener('click', () => {
    pause.classList.add('hidden');
    play.classList.remove('hidden');
    clearTimeout(timeouId); // setTimeout の返り値を取得し、それをストップ
  });

```


以上でスライドショーの完成です。
こうして順序立てて書いていくことで、勉強し始めた頃にぱっと見てもわからなかったことが少しずつわかるようになってきました。
そしていくつか簡単ながらプログラムを書いたことで、ある程度の流れを知ることができてきたように思えます。
まだまだ初心者なので、ん？と思って進めないことが多々ありますが、それもアウトプットしていくことで理解を深めると同時に、これをご覧になってくださった方が同じ疑問を持った際、少しでもお役に立てればと考えています。

今後も簡単なプログラムを学びながら、少し自分の色を入れていこうと思います。
どうぞ宜しくお願い致します。

## 完成したコード

```JavaScript:JavaScript

'use strict';

{
  let images = [
    {url: 'img/pic00.jpg', txt: {name: '紺瑠璃', color: '#164a84'},},
    {url: 'img/pic01.jpg', txt: {name: '天色', color: '#2ca9e1'},},
    {url: 'img/pic02.jpg', txt: {name: '翡翠色', color: '#38b48b'},},
    {url: 'img/pic03.jpg', txt: {name: '浅緑', color: '#88cb7f'},},
    {url: 'img/pic04.jpg', txt: {name: '萌黄', color: '#aacf53'},},
    {url: 'img/pic05.jpg', txt: {name: '山吹茶', color: '#c89932'},},
    {url: 'img/pic06.jpg', txt: {name: '一斤染', color: '#f5b199'},},
    {url: 'img/pic07.jpg', txt: {name: '浅蘇芳', color: '#a25768'},},

  ]


  let currentNum = 0;



  const name = document.getElementsByClassName('name');
  const color = document.getElementsByClassName('color');
  function setMainImage(image) {
    document.querySelector('main img').src = image.url;
    document.querySelector('main .name').textContent = `${image['txt'].name}`;
    document.querySelector('main .color').innerHTML = `カラーコード：<strong>${image['txt'].color}</strong>`;
  }

  setMainImage(images[currentNum]);

  function removeCurremtClass() {
    document.querySelectorAll('.thumbnails li')[currentNum].classList.remove('current');
  }
  function addCurremtClass() {
    document.querySelectorAll('.thumbnails li')[currentNum].classList.add('current');
  }

  const thumbnails = document.querySelector('.thumbnails');

  images.forEach((image, index) => {
    const li = document.createElement('li');
    if (index === currentNum) {
      li.classList.add('current');
    }
    li.addEventListener('click', () => {
      setMainImage(image);
      removeCurremtClass();
      currentNum = index;
      addCurremtClass();
    });

    const img = document.createElement('img');

    img.src = image.url;
    li.appendChild(img);
    thumbnails.appendChild(li);
  });


  const next = document.getElementById('next');
  next.addEventListener('click', () => {
  removeCurremtClass();
  currentNum++;
  if (currentNum === images.length) {
    currentNum = 0;
  }
  addCurremtClass();
  setMainImage(images[currentNum]);
});

  const prev = document.getElementById('prev');
  prev.addEventListener('click', () => {
    removeCurremtClass();
    currentNum--;
    if (currentNum < 0) {
      currentNum = images.length - 1;
    }
    addCurremtClass();
    setMainImage(images[currentNum]);
  });


    let timeouId;

  function playSlideShow() {
    timeouId = setTimeout(() => {
      next.click();
      playSlideShow();
    }, 300);
  }

    const play = document.getElementById('play');
    const pause = document.getElementById('pause');

    play.addEventListener('click', () => {
      play.classList.add('hidden');
      pause.classList.remove('hidden');
      playSlideShow();
    });
    pause.addEventListener('click', () => {
      pause.classList.add('hidden');
      play.classList.remove('hidden');
      clearTimeout(timeouId);
    });

}

```