只今、PHPを学習しております

素のJavaScriptで実装する単一横スクロールスライダーの秘密

こんにちは、トッドです。

モダンでお洒落なWEBサイトにはコンテンツをスライド形式で表示するSliderが完備されている事がありますよね。

自分で実装できたらすごく良いですよね。

ここでは、JavaScriptの基本的なDOM操作を使って実装する、スライド末尾がボタン管理でループし、横スクロールアクションで画像が切り替わるimgスライダーを紹介したいと思います。


完成デモ!


注目!
下記で紹介しているコードには、FontAwesomeのアイコンを使用しているので実装反映をする場合は、コチラのコードをheadタグ直前に挿入することをお忘れなく
HTML
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.13.1/css/all.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.1/js/all.min.js"></script>

似たようなコンテンツスライダーを簡単に実装することを可能にするSwiperというJavaScriptフレームワークがあります。

Swiperを使えば良いのですが、「自分で」という大切さを尊重したい方は下記参照してください。

※完成デモで使用している画像のサイズは、アスペクト比が16:9です。

下記参照コード↓

HTML
<div class="slider">
      <div class="slide">
        <ul>
          <li><img src="#" alt="" /></li>
          <li><img src="#" alt="" /></li>
          <li><img src="#" alt="" /></li>
        </ul>
      </div>
      <div class="controller">
        <div class="prev-btn btns">
          <i class="fas fa-angle-left fa-3x"></i>
        </div>
        <div class="indicator">
          <span id="active"></span>
          <span></span>
          <span></span>
        </div>
        <div class="next-btn btns">
          <i class="fas fa-angle-right fa-3x"></i>
        </div>
      </div>
    </div>

HTMLのli要素内にimgを挿入するときは、最後に表示させたい画像を1番最初に。それ以降は順番通りに設置してください。

CSS
.slider {
  position: relative;
  width: 416px;
  height: 300px;
  padding: 0;
  margin: 1rem auto;
  box-sizing: unset;
  border: 5px solid black;
  border-radius: 6px;
}
.slider .slide {
  width: 416px;
  height: 234px;
  padding: 0;
  margin: 0 auto;
  overflow: hidden;
}

.slider .slide img {
  padding: 0;
  margin: 0;
  width: 416px;
  height: 234px;
}

.slider .slide ul {
  width: 1248px;
  height: 234px;
  padding: 0;
  margin: 0;
  border: none;
  list-style: none;
  font-size: 0;
  position: relative;
}
.slider .slide li {
  padding: 0;
  margin: 0;
  display: inline-block;
  position: absolute;
  transition: 0.7s cubic-bezier(0.45, 0.06, 0.32, 1);
}

.slide li:nth-of-type(1) {
  left: -416px;
}
.slide li:nth-of-type(2) {
  left: 0px;
}
.slide li:nth-of-type(3) {
  left: 416px;
}

.controller {
  display: flex;
  width: 100%;
  height: 65px;
  margin: 0 auto;
  justify-content: center;
  align-items: center;
  background-color: rgba(255, 255, 255, 1);
  background-image: repeating-linear-gradient(
    -45deg,
    transparent,
    transparent 10px,
    rgba(219, 219, 219, 1) 10px,
    rgba(219, 219, 219, 1) 19px
  );
}
.controller .prev-btn {
  margin-left: 3rem;
  cursor: pointer;
  color: #181818;
}
.controller .next-btn {
  margin-right: 3rem;
  cursor: pointer;
  color: #181818;
}

.controller .indicator {
  display: flex;
  width: 80px;
  height: 16px;
  margin: 0 auto;
  justify-content: center;
  align-items: center;
  background: #181818;
  border-radius: 10px;
}

.indicator span {
  width: 8px;
  height: 8px;
  background: whitesmoke;
  border-radius: 50%;
  padding: 0;
  margin: 0 4px 0 4px;
}

#active {
  background: red;
}

CSSはアスペクト比が16:9の画像サイズ 416x234pxでガチガチにしているので触る場合は随所を見直してください。

JavaScript
const btn = document.getElementsByClassName("btns");
const preBtn = document.querySelector(".prev-btn");
const nextBtn = document.querySelector(".next-btn");

for (let i = 0; i < btn.length; i++) {
  btn[i].addEventListener("click", () => {
    const slide = document.querySelector(".slide ul").children;
    const Indicator = document.querySelector(".indicator").children;

    const lastSlideIndex = slide.length - 1;
    const firstSlideIndex = 0;
    const lastIndicatorIndex = Indicator.length - 1;
    const firstIndicatorIndex = 0;

    const firstItem = slide.item(firstSlideIndex);
    const lastItem = slide.item(lastSlideIndex);
    const firstIndicator = Indicator.item(firstIndicatorIndex);
    const lastIndicator = Indicator.item(lastIndicatorIndex);

    if (btn[i] === preBtn) {
      setTimeout(() => {
        firstItem.parentNode.insertBefore(lastItem, firstItem);
        firstIndicator.parentNode.insertBefore(
          firstIndicator,
          lastIndicator.nextSibling
        );
      }, 400);
    } else if (btn[i] === nextBtn) {
      setTimeout(() => {
        lastItem.parentNode.insertBefore(firstItem, lastItem.nextSibling);
        firstIndicator.parentNode.insertBefore(lastIndicator, firstIndicator);
      }, 400);
    }
  });
}

setTimeoutはボタン連打対策の応急処置です。

上記のコードをコピペしても動かないケースがあると思います。

問題はおそらく、シンプルにJavaScriptが読み込まれていないか?、あるいはWordPressの自動整形機能が邪魔をしているかです。

最後まで読んでいただきありがとうございました。

コメントを残す

メールアドレスが公開されることはありません。