JavaScript - 自動で画像が切り替わるスライドショーの作り方

クリックもできる自動再生スライドショー

今回紹介するのは、一定間隔で画像が切り替わるスライドショーの作り方です。画像の下にナビケーションボタンを配置し、自動再生している間にも手動で画像を切り替えることができるようにします。

この記事を読むと分かること

  • document.createElement( )
  • appendChild()
  • classList.add()
  • classList.remove()
  • forEach()
  • setInterval()
  • clearInterval()

サンプルプロジェクト

最初に、スライドショーの動きを確認しておきましょう。画像の下にあるドットは、何番目の画像が表示されているのかを示すナビゲーションボタンです。表示されている画像のボタンはオレンジ色になります。画像は自動で切り替わるほか、ボタンをクリックして切り替えることもできます。

スライドショーのサンプルプロジェクト

HTML

まずは HTML です。画像 <img> はお好みのものをいくつか用意し、src 属性に画像へのパスを書きます。ナビゲーションコンテナ nav-container <div> は、この段階では空っぽです。このあとの JavaScript で、ナビゲーションボタンを作っていきます。

<div class="slider-container">

  <div class="image-container">
    <img src="https://images.unsplash.com/photo-1481349518771-20055b2a7b24?w=900&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8NDd8fGZydWl0ZXN8ZW58MHx8MHx8fDA%3D" alt="one banana">
    <img src="https://images.unsplash.com/photo-1528821128474-27f963b062bf?w=900&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MzR8fGZydWl0ZXN8ZW58MHx8MHx8fDA%3D" alt="two cherries">
    <img src="https://images.unsplash.com/photo-1457803097035-3ace37af34a7?w=900&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MTEwfHxmcnVpdGVzfGVufDB8fDB8fHww" alt="three apples">
    <img src="https://images.unsplash.com/photo-1595475207225-428b62bda831?w=900&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MTU0fHxmcnVpdGVzfGVufDB8fDB8fHww" alt="four slices of watermelon">
  </div>

  <!-- ナビゲーションコンテナ -->
  <div class="nav-container"></div>

</div>

CSS

続いて CSS です。表示する画像とナビゲーションボタンの色は、JavaScript でクラスの付け外しすることで切り替えていきます。表示する画像に付け加えるクラスを image-active 、ボタンの色を変えるためのクラスを btn-active として用意しておきましょう。

body {
  margin: 0;
  padding: 0;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: #454545;
}
  
.slider-container {
  position: relative;
  display: flex;
  width: 800px;
  height: 500px;
  border: 5px solid lightgray;
}

/* 画像コンテナ */
.image-container {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 90%;
  object-fit: cover;
}

/* 画像 */
img {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0; /* 透明(非表示)*/
  transition: opacity 0.5s;
}

/* 画像を表示するためのクラス */
img.image-active {
  opacity: 1; /* 不透明(表示)*/
  transition: opacity 0.5s;
}

/* ナビゲーションコンテナ */
.nav-container {
  position: absolute;
  bottom: 0;
  width: 100%;
  height: 10%;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: lightgray;
}

/* 新しく作成したボタンに追加するクラス */
.nav-btn {
  height: 20px;
  width: 20px;
  display: inline-block;
  margin: 10px;
  background-color: #0d7df5; /* 青色 */
  border-radius: 50%;
  border: none;
  cursor: pointer;
}

/* ボタンの色を変えるためのクラス */
.nav-btn.btn-active {
  background-color: #f99f3e; /* オレンジ色 */
}

.nav-btn:hover{
  box-shadow: 0 0 5px 3px white;
}

ブラウザには下のように表示されます。画像は opacity: 0 で透明にしてあるので見えません。

画像とナビゲーションボタンは表示されていない

JavaScript

JavaScript のコーディングは、大きく3段階に分けて考えていきますよ。

  1. 要素の取得と変数の宣言
  2. ボタンを作成しクリックで画像を切り替える
  3. 自動で次の画像へ切り替える

要素の取得と変数の宣言

最初に、JavaScript で動きをつけられるように要素を取得しておきましょう。

  • 用意したすべての画像を querySelectorAll() メソッドでまとめて取得し、変数 images に格納します。
  • ボタンを表示するエリアを、変数 navContainer で参照できるようにしておきます。ボタンはこのあと JavaScript で生成していきます。
// すべての画像
const images = document.querySelectorAll('img');
// ナビゲーションコンテナ
const navContainer = document.querySelector('.nav-container');

次に行うのは、変数の宣言です。

  • 用意した画像の総数を images.length で取得し、変数 totalImages に格納します。
  • 表示する画像を指定する変数を imageIndex とし、0 で初期化しておきます。
  • 自動再生に使うタイマーを入れておくための変数 interval を用意します。タイマーをキャンセルするときにこの変数が必要になります。
// 画像の総数
const totalImages = images.length;
// 表示する画像を指定するインデックス
let imageIndex = 0;
// タイマー
let interval;

要素の取得と変数の宣言ができたら、スライドショーに動きをつけるためのコードを書いていきましょう。

ボタンを作成しクリックで画像を切り替える

今回作るスライドショーは、自動再生機能だけでなく、クリックに反応するナビゲーションボタンも設置しますよ。まずは、クリックで画像を切り替えられるようにしていきます。次の手順でコードを書いていきましょう。

  1. 画像と同じ数のボタンを作る
  2. すべてのボタンにクリックイベントを追加する
  3. 画像とボタンを更新する

画像と同じ数のボタンを作る

画像の下部に設置するナビゲーションボタンは、画像と同じ数だけ必要です。ボタンは HTML で作っておくこともできますが、画像の増減に簡単に対応できるように、今回は JavaScript で作っていきますよ。

JavaScript で新しく要素を作るため使うのは、document.createElement() メソッドです。document.createElement( ) メソッドは、括弧 () に指定されたタグの名前の要素を生成します。ここでは、ナビゲーションボタンを <button> 要素で作ります。

// 新しいボタン要素を作成
const button = document.createElement('button');

新しく作ったボタンには、 classList.add() メソッドでクラスを追加します。追加するクラス nav-btn の内容は、先ほどの CSS を参照してくださいね。

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

// 新しく作成したボタンにクラスを追加
button.classList.add('nav-btn');

続けて、appendChild() メソッドを使って、ボタンを表示するエリアである navContainer に追加します。

const button = document.createElement('button');
button.classList.add('nav-btn');

// 新しく作成したボタンをナビゲーションコンテナに追加
navContainer.appendChild(button);

以上3つの文を、for 文を使って繰り返し処理し、画像と同じ数のボタンを作りましょう。

// 画像と同じ数のボタンを作成
for (let i = 0; i < totalImages; i++) {
  const button = document.createElement('button');
  button.classList.add('nav-btn');
  navContainer.appendChild(button);
}

for 文について詳しくは以下の記事をご覧ください。

JavaScript - for ループ (繰り返し) の基本【初心者向け】
繰り返し処理を実行するために使われる for 文の書き方や、ループの中で使われる break 文と continue 文について、プログラミング初心者の方でも分かりやすいように簡単なコードを例にして解説します。

ブラウザには下のように表示されます。用意した画像の枚数によってボタンの数も変わりますよ。

画像の下部に青色のナビゲーションボタンが4つ表示される

すべてのボタンにクリックイベントを追加する

ナビゲーションボタンを作ったら、今度は、一つひとつのボタンをクリックできるようにしていきます。そのために、生成したすべてのボタンをまとめて取得し、変数 buttons に格納しましょう。

// すべてのボタンをまとめて取得
const buttons = document.querySelectorAll('.nav-btn');

forEach() メソッドを使って、すべてのボタンにクリックイベントを追加します。括弧 () に指定する関数の内容は、「ボタン一つひとつにクリックイベントを追加して、クリックされたボタンと同じインデックスの画像を表示する」という処理です。

// すべてのボタンにクリックイベントを追加
buttons.forEach(() => {
  
  // ボタン一つひとつにクリックイベントを追加、
  // クリックされたボタンと同じインデックスの画像を表示する処理;
  // …
  
});

関数には二つの引数を指定します。処理の対象となる要素を受け取る button と、処理の対象となっている要素のインデックスを受け取る index です。

// 二つの引数を指定
buttons.forEach((button,index) => {
  
  // ボタン一つひとつにクリックイベントを追加、
  // クリックされたボタンと同じインデックスの画像を表示する処理;
  // …
  
});

ボタン一つひとつにクリックイベントを追加するコードは、以下のようになります。ボタンがクリックされたら、クリックされたボタンと同じインデックスの画像を表示するようにしましょう。

buttons.forEach((button,index) => {

  // ボタン一つひとつにクリックイベントを追加
  button.addEventListener('click',() => {

  // クリックされたボタンと同じインデックスの画像を表示する処理;
  // …
    
  });

});

クリックされたボタンと同じインデックスの画像を表示するためには、クリックされたボタンのインデックス index を、表示する画像のインデックス imageIndex に代入します。そうすることで、最初のボタンがクリックされたら最初の画像を、2番目のボタンがクリックされたら2番目の画像を指定できるようになりますよ。

buttons.forEach((button,index) => {
  button.addEventListener('click',() => {

    // 表示する画像のインデックスをクリックされたボタンのインデックスと同じにする
    imageIndex = index;

  });
});

ボタンをクリックして表示する画像を指定したら、関数 updateSlider を実行します。関数 updateSlider は、画像とボタンを更新する関数で、このあと定義します。

buttons.forEach((button,index) => {
  button.addEventListener('click',() => {
    imageIndex = index;
    
    // 画像とボタンを更新
    updateSlider();

  });
});

ここまでで、画像と同じ数のナビゲーションボタンを作成し、ボタンをクリックして表示する画像を指定できるようになりました。

画像とボタンを更新する

ここからは、画像とボタンを更新する関数 updateSlider を定義していきましょう。内容は、「表示する画像を切り替えて、それと一致するボタンの色を変える」という処理です。

// 画像とボタンを更新
function updateSlider() {

  // 表示する画像を切り替えてボタンの色を変える処理;
  // …
  
}

画像とボタンの更新は、クラスの付け外しをすることで行います。まずは、classList.remove() メソッドを使って、すべての画像から image-active を、すべてのボタンから btn-active クラスを取り外しましょう。これによって、一旦、すべての画像が非表示に、すべてのボタンが青色になりますよ。

function updateSlider() {

  // すべての画像からimage-activeクラスを取り外す
  images.forEach(image => {
    image.classList.remove('image-active');
  });

  // すべてのボタンからbtn-activeクラスを取り外す
  buttons.forEach(button => {
    button.classList.remove('btn-active');
  });

}

次に、classList.add() メソッドで、表示する画像に image-active クラスを、それと同じインデックスのボタンに btn-active クラスを追加します。これによって、指定された画像が表示され、それと一致するボタンがオレンジ色になりますよ。表示する画像は、変数 imageIndex を使って images[imageIndex] のように指定します。色を変えるボタンも同じです。

function updateSlider() {
  images.forEach(image => {
    image.classList.remove('image-active');
  });
  buttons.forEach(button => {
    button.classList.remove('btn-active');
  });

  // 表示する画像を変数imageIndexで指定しimage-activeクラスを追加
  images[imageIndex].classList.add('image-active');

  // 色を変えるボタンを変数imageIndexで指定しbtn-activeクラスを追加
  buttons[imageIndex].classList.add('btn-active');

}

以上で、画像とボタンを更新する関数 updateSlider を定義できました。この段階では、ボタンをクリックすることでのみ画像を切り替えることができます。

自動で次の画像へ切り替える

さて、続いては、自動再生機能です。一定時間毎に次の画像へ自動的に切り替わるようにします。次の手順でコードを書いていきましょう。

  1. 次の画像を指定して表示する
  2. タイマーを設定し一定時間毎に自動で切り替える
  3. タイマーをキャンセルしタイミングのズレを直す

次の画像を指定して表示する

次の画像を順番に表示するために、関数 nextImage を次のように定義しましょう。

  • 変数 imageIndex の値を1増やして、次の画像を指定する
  • もし、指定する画像が最後の画像のインデックスより大きいなら
  • 変数 imageIndex の値を 0 にして最初の画像を指定する
  • 画像とボタンを更新する
// 次の画像を指定して表示
function nextImage() {
  imageIndex++;
  if (imageIndex > totalImages - 1) {
    imageIndex = 0;
  }
  // 画像とボタンを更新
  updateSlider();
}

次の画像を指定する方法については、以下の記事で詳しく解説しているので参考にしてください。

JavaScript - クリックで切り替わる画像スライダーの作り方
ボタンをクリックすると画像が切り替わる画像スライダーを作ります。画像をいくつか用意して、右矢印ボタンで次の画像を、左矢印ボタンで前の画像を表示するようコーディングします。

タイマーを設定し一定時間毎に自動で切り替える

自動再生の関数 autoPlay を定義します。一定時間で自動的に画像を切り替えるために、setInterval() メソッドで関数 nextImage を呼び出しましょう。ここでは呼び出す間隔を 3000 とし、3秒毎に次の画像へ切り替わるようにします。

// 次の画像へ自動再生
function autoPlay() {
  interval = setInterval(nextImage, 3000);
}

タイマーをキャンセルしタイミングのズレを直す

さらに、タイマーを一旦キャンセルする関数 resetInterval を用意します。これは、ボタンのクリックで画像を切り替えた場合に、自動再生のタイミングがズレるのを直すための関数です。

clearInterval() メソッドの括弧 () 内に、自動再生のタイマーを格納した変数 interval を指定すると、タイマーを停止することができます。その後再び自動再生の関数 autoPlay を呼び出すことで、3秒間隔での自動再生が再開されます。

// 自動再生を一旦停止してから再び再生
function resetInterval() {
  clearInterval(interval);
  autoPlay();
}

この関数 resetInterval は、ボタンのクリックで画像を切り替えたときに必要になるので、以下のようにコードを追加しましょう。

// すべてのボタンにクリックイベントを追加
buttons.forEach((button,index) => {
  button.addEventListener('click',() => {
    imageIndex = index;
    updateSlider();

    // 自動再生を一旦停止してから再び再生
    resetInterval();

  });
});

スライドショーを開始する

さて、これが最後のコードです。画像とボタンを更新する関数 updateSlider と、自動再生する関数 autoPlay を呼び出して、スライドショーを開始しましょう。

// スライドショーを開始
updateSlider();
autoPlay();

完成コード

クリックでの画像切り替えも可能な、自動再生するスライドショーのコードが完成です。

//**********************
// スライドショーのコード
//**********************

const images = document.querySelectorAll('img');
const navContainer = document.querySelector('.nav-container');
const totalImages = images.length;
let imageIndex = 0;
let interval;

// 画像と同じ数のボタンを作成
for (let i = 0; i < totalImages; i++) {
  const button = document.createElement('button');
  button.classList.add('nav-btn');
  navContainer.appendChild(button);
}

// 作成したボタンを操作できるようにすべてのボタンをまとめて取得
const buttons = document.querySelectorAll('.nav-btn');

// すべてのボタンにクリックイベントを追加
buttons.forEach((button,index) => {
  button.addEventListener('click',() => {
    imageIndex = index;
    updateSlider();
    resetInterval();
  });
});

// 画像とボタンを更新
function updateSlider() {
  images.forEach(image => {
    image.classList.remove('image-active');
  });
  buttons.forEach(button => {
    button.classList.remove('btn-active');
  });
  images[imageIndex].classList.add('image-active');
  buttons[imageIndex].classList.add('btn-active');
}

// 次の画像を指定して表示
function nextImage() {
  imageIndex++;
  if (imageIndex > totalImages - 1) {
    imageIndex = 0;
  }
  updateSlider();
}

// 次の画像へ自動再生
function autoPlay() {
  interval = setInterval(nextImage, 3000);
}

// 自動再生を一旦停止してから再び再生
function resetInterval() {
  clearInterval(interval);
  autoPlay();
}

// スライドショーを開始
updateSlider();
autoPlay();

See the Pen JavaScript - Automatic and Manual Slideshow by Pyxofy (@pyxofy) on CodePen.


まとめ

今回は、一定の間隔で自動的に切り替わるだけでなく、クリックして表示する画像を変えることもできるスライドショーの作り方を紹介しました。

コードのポイントをまとめると以下のようになります。

  • 画像と同じ数だけ必要な <button> 要素を JavaScript で生成
  • 複数の画像やボタンに対して同じ処理を実行するために forEach() メソッドを利用
  • 画像の表示/非表示やボタンの色はクラスの付け外しによって切り替えを実行
  • 自動再生のタイミングは一旦タイマーを停止してから再開することで調整

最後まで読んでいただき、ありがとうございます。この記事をシェアしてくれると嬉しいです!

SNSで Pyxofy とつながりましょう! LinkedInThreadsMastodon X (Twitter) @pyxofyFacebook

関連記事

JavaScript - ボタンを押して表示を切り替える方法
ボタンをクリックしてコンテンツの表示 / 非表示を切り替えたり、ウェブページの表示をダークモードにする方法を解説します。CSS に切り替えたいクラスを追加して toggle() メソッドで切り替えるだけなので簡単です。
CSS Art
Articles for creating CSS Art.
CSS Animation
Articles for creating CSS Animation.
Scratch - Pyxofy
Scratch 3.0の使い方を、プログラミング初心者や子どもにも分かりやすく紹介しています。