トップへ戻る
BLOGS

JS 自作スライドショー制作まとめ①(クリック切り替え)

JS 自作スライドショー制作まとめ①(クリック切り替え)

はい。

今回はJavaScript、CSSのみを使用した、スライドショーの制作記録をまとめていきます。

スライドショーの種類ごとにコードの記録をそのまま残して行こうと思います

というのもスライドショーはどのサイトでも見られるほどメジャーなアニメーションですが、今の所私のサイトでは実用に至る箇所がなかったため、

せっかく覚えたものをそのままコピペできるように残しておこうと思います。

まずは私の体感一番遭遇するタイプから、、

アイコンや画像クリックで切り替わるスライダー

<main>
 <div class="mainImage">
  <div class="prevImage fas fa-chevron-left" id="prevImage"></div>
  <div class="nextImage fas fa-chevron-right" id="nextImage"></div>
    <img id="mainImage">
    <div class="currentSlideNumber" id="currentSlideNumber"></div>
 </div>
 <ul id="imagelist" class="imagelist"></ul>
</main>

HTML解説

今回は矢印のアイコンを表示するのにFontAwesomeを使用しています

CDNをヘッドに書き込んでクラスを指定するだけですね

そして<img id=”mainImage”>にJSで属性を指定して画像を切り替えます

currentSlideNumberは現在のページを表示できるようにし、

さらに<ul id=”imagelist”>ではすべての画像を表示しこちらをクリックしても切り替えれるようにリンクさせます

まずはこの要素たちをJSで取得していきましょう

const imageTotalNumber = 6,
      mainImageElement = document.getElementById('mainImage'),
      imageListElement = document.getElementById('imagelist'),
      prevImageElement = document.getElementById('prevImage'),
      nextImageElement = document.getElementById('nextImage');
let currentSlideNumber = 1;

全てにIDを振っておいたので、簡単に取得できますね

imageTotalNumberにはすべての画像の数を入れます。

currentSlideNumberは現在の表示になるためここでは letで変数にしておきます

それでは最初の画像を属性値として入れていきます

mainImageElement.setAttribute('src','img/teien1.jpg');

セットアトリビュートで属性値として画像を入れることが出来ます

まずはリストとしてすべての画像を並べてその切替までやってしまいましょう

for (let i = 0; i < imageTotalNumber; i++) {
  const liElement = document.createElement('li');
  liElement.style.backgroundImage = `url('img/teien${i + 1}.jpg')`;
  liElement.addEventListener('click',() => {
    mainImageElement.setAttribute("src", `img/teien${i + 1}.jpg`);
  })
  imageListElement.appendChild(liElement);
}

まずfor文のループを回してすべての画像枚数分繰り返します

createElementではliタグを生成します

style.backgroundImageはタグに直接スタイルを指定できるので、その中身としてテンプレートリテラルで変数の連結を行い、同じような名前の画像名としての数値を順番に入れています

そしてそのタグに対して、イベントリスナーを仕掛けておきクリックした際にその番号の画像になるようにしておきます

最後に作成したタグを入れれる様にappendChildをしておきます

この後はアイコンとの連携をするわけですが、

現在の番号として整合性をとれるようにしておきましょう

currentSlideNumber = i + 1;

この記述をイベントリスナーの中に入れておくことで番号は揃います

ループは0から回っているためプラス①することで一致します

それではアイコンも作っていきます

「前へ」アイコンのクリック動作を指定します

prevImageElement.addEventListener('click', () => {
  if(currentSlideNumber !== 1) {
    currentSlideNumber--
    mainImageElement.setAttribute("src",
    `img/teien${currentSlideNumber}.jpg`);
  }
})

同じ様にイベントリスナーを仕掛ける訳ですが現在の番号が最初の画像であったらいけないため条件分岐での設定をします

まずcurrentSlideNumber–で現在の番号から①マイナスします

後は上の応用ですね

ただ画像の番号の部分はcurrentSlideNumberとすることで一つ前に戻れますね

同じ様に「次へ」のボタンも実装しましょう

nextImageElement.addEventListener('click', () => {
  if(currentSlideNumber !== imageTotalNumber) {
    currentSlideNumber++
    mainImageElement.setAttribute("src", `img/teien${currentSlideNumber}.jpg`);
  }

上のコードと違うのは条件分岐、

最後の画像でないことが条件ですね

そして現在の番号にプラスする形で属性値を出力します。

しかしこのままでは矢印アイコンが最初か最後でも見た目が同じなのでユーザビリティが良くないため、

クラスを付け替えることで分かりやすくしてあげます

現在の番号でクラスを付与する

function changeSlideStatus() {
  if (currentSlideNumber === 1) {
    prevImageElement.classList.add('inActive')
  } else {
    prevImageElement.classList.remove('inActive')
  }
  if (currentSlideNumber === imageTotalNumber) {
    nextImageElement.classList.add('inActive')
  } else {
    nextImageElement.classList.remove('inActive')
  }
  document.getElementById('currentSlideNumber').textContent = `${currentSlideNumber} / ${imageTotalNumber}`
}
changeSlideStatus()

今までの応用ですね、条件分岐で最初とそうでない場合のクラスを付け替えます

このクラスに対してCSSで変更を書いてあげれば(色を変えたり、そもそも消したり)

すればわかりやすくなります。

そして現在の番号を出力できるようにしましょう

.textContent = `${currentSlideNumber} / ${imageTotalNumber}`の部分ですね

最後にこの処理を関数化して各出力のたびに呼び出してあげれば、現在の番号もリアルタイムになりますし、最初か最後の画像ならクラスが変わるようになりました。

最後にCSSと一緒に完成コードを貼り付けます

JS

const imageTotalNumber = 6,
      mainImageElement = document.getElementById('mainImage'),
      imageListElement = document.getElementById('imagelist'),
      prevImageElement = document.getElementById('prevImage'),
      nextImageElement = document.getElementById('nextImage');
let currentSlideNumber = 1;

mainImageElement.setAttribute('src','img/teien1.jpg');

function changeSlideStatus() {
  if (currentSlideNumber === 1) {
    prevImageElement.classList.add('inActive')
  } else {
    prevImageElement.classList.remove('inActive')
  }
  if (currentSlideNumber === imageTotalNumber) {
    nextImageElement.classList.add('inActive')
  } else {
    nextImageElement.classList.remove('inActive')
  }
  document.getElementById('currentSlideNumber').textContent = `${currentSlideNumber} / ${imageTotalNumber}`
}
changeSlideStatus()
for (let i = 0; i < imageTotalNumber; i++) {
  const liElement = document.createElement('li');
  liElement.style.backgroundImage = `url('img/teien${i + 1}.jpg')`;
  liElement.addEventListener('click',() => {
    mainImageElement.setAttribute("src", `img/teien${i + 1}.jpg`);
    currentSlideNumber = i + 1;
    changeSlideStatus();
  })
  imageListElement.appendChild(liElement);
}
prevImageElement.addEventListener('click', () => {
  if(currentSlideNumber !== 1) {
    currentSlideNumber--
    mainImageElement.setAttribute("src", `img/teien${currentSlideNumber}.jpg`);
    changeSlideStatus();
  }
})
nextImageElement.addEventListener('click', () => {
  if(currentSlideNumber !== imageTotalNumber) {
    currentSlideNumber++
    mainImageElement.setAttribute("src", `img/teien${currentSlideNumber}.jpg`);
    changeSlideStatus();
  }
})

CSS

// スイッチ式スライダー
.mainImage {
  max-width: 1100px;
  width: 100%;
  margin: 0 auto 100px;
  padding: 0 40px;
  position:relative;
  user-select: none;
  .prevImage,
  .nextImage {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    transition: 0.3s;
    cursor: pointer;
    &.inActive {
      opacity: 0.3;
      pointer-events: none;
    }
    &:hover {
      opacity: 0.5;
    }
    &:before {
      font-size: 30px;
      color: #555;
    }
  }
  .prevImage {
    left: 0;
  }
  .nextImage {
    right: 0;
  }
  .currentSlideNumber {
    text-align: center;
    margin-top: 20px
  }
}
.mainImage img {
  width: 100%;
  box-shadow: 0px 5px 15px 0px rgba(0,0,0,0.35);
}
.imagelist {
  max-width: 1000px;
  width: 100%;
  margin: 0 auto 100px;
  display: flex;
  flex-wrap: wrap;
  gap: 30px 3.5%;
}
.imagelist li {
  width: 31%;
  height: 200px;
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;
  list-style: none;
  cursor: pointer;
  box-shadow: 0px 5px 15px 0px rgba(0,0,0,0.35);
  transition: 0.3s;
  &:hover {
    opacity: 0.7;
    transform: scale(1.05);
  }
}

コメントをお待ちしております

お気軽にコメントをどうぞ。

CAPTCHA