1
1

More than 1 year has passed since last update.

サムネ付きスライドショー作りました

Posted at

便利なプラグインがたくさんあるスライドショーですが、できれば自作のものを使いたいと思いjsで開発しました。

ベースを作って自分のストック用として手動、自動、モーダルと1セット揃えました。
この際、逃げ腰だったタッチイベントにも挑戦。

手動スライド

サンプルサイト>

touch.html
    <div id="slidePanel">
    <!-- 表示領域 -->
      <div class="panel">
        <figure class="panelImg">
        <!-- デフォルトに画像一つ置いておく -->
          <img src="./image/slide1.jpg" alt="">
        </figure>
      </div>
    <!-- prevボタンとnextボタン -->
      <div id="prev"><img src="./image/prev.svg" alt="前へ"></div>
      <div id="next"><img src="./image/next.svg" alt="次へ"></div>
    </div>
    <!-- //.slidePanel -->

    <!-- サムネイル スライド画像を格納 -->
    <ul id="thumb">
      <li class="thumbLi act"><img src="./image/slide1.jpg" alt=""></li>
      <li class="thumbLi"><img src="./image/slide2.jpg" alt=""></li>
      <li class="thumbLi"><img src="./image/slide3.jpg" alt=""></li>
      <li class="thumbLi"><img src="./image/slide4.jpg" alt=""></li>
      <li class="thumbLi"><img src="./image/slide5.jpg" alt=""></li>
      <li class="thumbLi"><img src="./image/slide6.jpg" alt=""></li>
    </ul>

普通だったらスライドのブロックに画像をliで書き出しますが、サムネイルのliに格納して非表示にしました。
actクラスでアクティブになっている要素と紐付けし、actが付与されたli直下のimgを取得します。
サムネをクリックした時、この方が分かりやすいと思ったもので。

・下準備 サイズ設定

myslide.js
//スライド一つ分の長さを取得
 let imgW;
 const panelImg = $('.panelImg');
  //スライド幅のレスポンシブ
  function slideW(){
    if(window.innerWidth > 768) {
      imgW = $('img',panelImg).width();
    } else {
      imgW = $(window).width();
    }
  }
  slideW();
  //次の画像をセットするので幅を追加しておく
  panelImg.width(imgW * 2);
  //リサイズ
  $(window).on('resize',function(){
    slideW();
    panelImg.width(imgW * 2);
  });

・nextボタンの実行
スライド中、クリック連打を防ぐ為if分で制御しました。
nextボタンが押されたら、actクラスは次のliへ付け変わります。

myslide.js
  let click = true;
  const next = $('#next');
  const prev = $('#prev');
  let nextImg, prevImg, cloneImg;

  //次へ
  function nextSlide(){
    //連打クリック禁止
    if(click == true){
      click = false;
      //actの次のliを取得
      nextImg = $('.act').next();
      //クローンしないと元データが消えてしまった
      cloneImg = $(nextImg).children('img').clone();
      panelImg.append(cloneImg);
      //actの付替え
      $(nextImg).addClass('act').siblings().removeClass('act');
      //スライド
      panelImg.stop().animate({'margin-left': imgW * -1},600,'swing',
      function(){
        $('img:first-child',this).remove();
        $(this).css('margin-left', 0);
      //クリックできる状態へ
        click = true;
      });
    }
  }

  next.on('click',function(){
    nextSlide();
    //ナビの表示非表示
    navChange();
  });

・前へ
nextの逆です。
左側に画像を足すので、予めmarginをマイナス値に。

myslide.js
  //前へ
  function prevSlide(){
    //連打クリック禁止
    if(click == true){
      click = false;
      prevImg = $('.act').prev();
      cloneImg = $(prevImg).children('img').clone();
      //スライドブロックを画像一つ分マイナスに
      panelImg.prepend(cloneImg).css('margin-left',imgW * -1);
      $(prevImg).addClass('act').siblings().removeClass('act');
      //スライドはmargin-leftを0に
      panelImg.stop().animate({'margin-left': 0},600,'swing',
      function(){
        $('img:last-child',this).remove();
        click = true;
      });
    }
  }

  prev.on('click',function(){
    prevSlide();
    //ナビの表示非表示
    navChange();
  });

・ナビの表示制御
最初だったらprevを非表示、最後だったらnextを非表示に。
ナビが隠れることによってスライドは不可になります。

myslide.js
  navChange();
  //ナビの処理
  function navChange(){
    if($('#thumb li:last-child').hasClass('act')) {
      next.css('display','none');
      prev.css('display','block');
    } else if($('#thumb li:first-child').hasClass('act')) {
      prev.css('display','none');
      next.css('display','block');
    } else {
      prev.css('display','block');
      next.css('display','block');
    }
  }

・サムネイルクリック
画像指定以外、ほぼnextと同じです。

myslide.js
  //サムネイルクリック
  let point,imgNum;
  $('#thumb li').on('click',function(){
    //連打クリック禁止
    if(click == true){
      click = false;
      //クリックした場所を検索
      point = $('#thumb li').index(this);
      $(this).addClass('act').siblings().removeClass('act');
      imgNum = $('#thumb li').eq(point);
      //cloneではない方法で取ってみる
      panelImg.append('<img src="'+ $('img',imgNum).attr('src') +'" alt="">');
      panelImg.stop().animate({'margin-left': imgW * -1},600,'swing',
      function(){
        $('img:first-child',this).remove();
        $(this).css('margin-left', 0);
        click = true;
      });
      navChange();
    }
  });

・touchイベント
最後と最初の画像の場合、スワイプ制御したかったので、スワイプ不可の値として’stop’を代入しています。値は’left’と’right’以外は何でもいいです。

myslide.js
  //touchイベント
    let moveX, posiX;

    /* 指が触れたか検知 */
    $('.panel').on('touchstart', start_check);

    /* 指が動いたか検知 */
    $('.panel').on('touchmove', move_check);

    /* 指が離れたか検知 */
    $('.panel').on('touchend', end_check);

    //タッチ開始時の処理
    function start_check(e) {
      /* 現在の座標取得 */
      posiX = getX(e);
      /* 移動距離状態を初期化 */
      moveX = '';
    }

    //スワイプ中の処理
    function move_check(e) {
      if (posiX - getX(e) > 20) // 20px以上移動でスワイプと判断
          {
      /* 右→左と判断 */
          if($('#thumb li:last-child').hasClass('act')){
             //画像が最後だったら移動しない
             moveX = 'stop';
            } else {
             moveX = 'left';
            }
          } else if (posiX - getX(e) < -20)  // 20px以上移動でスワイプと判断
          {
          /* 左→右と判断 */
            if($('#thumb li:first-child').hasClass('act')){
              //画像が最初だったら移動しない
              moveX = 'stop';
              } else {
              moveX = 'right';
              }
          }
      }

      //指が離れた時の処理
    function end_check(e){
      if(moveX == 'left'){
        nextSlide(e);
        navChange();
      } else if(moveX == 'right'){
        prevSlide(e);
        navChange();
      }
    }

    function getX(e) {
      //横方向の座標を取得
      return e.originalEvent.touches[0].pageX;
    }

自動スライド

サンプルサイト>

手動スライドにsetTimeoutをつけました。
エンドレスにループさせた為、navChange()は無くしてカルーセルにしています。
スワイプ不可の条件文も外しています。

myslide_timer.js
  function slideStart(){
      nextSlide();
      timerID = setTimeout(slideStart, 3000);
  }
  //タイマー起動
  slideStart();

横幅100%自動スライド

サンプルサイト>

ファーストビューでよく見かけるブラウザ幅100%で端が見えているタイプです。
cssはかなり変更しました。

touch_timer_wide.html
<div class="panel">
    <figure class="panelImg">
        <img src="./image/slide_big6.jpg" alt="">
        <img src="./image/slide_big1.jpg" alt="">
        <img src="./image/slide_big2.jpg" alt="">
    </figure>
</div>

スライド領域のデフォルト画像は3つセットにし、真ん中がアクティブになります。なので次の画像指定は2つ先のものを取得します。
nextメソッドを入れたセレクタを変数に代入し、再度nextメソッドを使います。

myslide_timer_wide.js
function nextSlide(){
    //カルーセルにする為、最後のliになったら最初のliを指定
    if($('#thumb li:last-child').hasClass('act')){
      nextImg = $('#thumb li:first-child');
    } else {
      nextImg = $('.act').next();
    }

    if($('#thumb li:nth-last-child(2)').hasClass('act')){
      //画像クローン
      cloneImg = $('#thumb li:first-child').children('img').clone();
    } else {
    //画像クローンは二つ先を取得
      cloneImg = $(nextImg).next().children('img').clone();
    }

    panelImg.append(cloneImg);
    //actの付替え
    $(nextImg).addClass('act').siblings().removeClass('act');
    //スライド
    panelImg.stop().animate({'margin-left': imgW * -2},800,'swing',
    function(){
      $('img:first-child',this).remove();
      $(this).css('margin-left', imgW * -1);
      click = true;
    });
  }

モーダルスライド

サンプルサイト>

モーダルウィンドウが浮かび上がってからattrメソッドで切り替わる仕様です。
サムネイルに画像の他、htmlデータも格納しました。

touch_modal.html
<!-- オーバーレイ -->
  <div id="overlay">
    <!-- 表示領域 -->
    <div id="slidePanel">
      <!-- サムネのデータより呼び出し -->
      <figure class="panelImg">
      <!-- attrメソッドで差し替え -->
        <img src="./image/slide1.jpg" alt="">
      </figure>
      <article id="modal_contents">
        <!-- htmlメソッドで丸ごと上書き -->
      </article>

      <div id="prev"><img src="./image/prev.svg" alt="前へ"></div>
      <div id="next"><img src="./image/next.svg" alt="次へ"></div>
      <div id="close_modal">×</div>
    </div>
    <!-- //.slidePanel -->
  </div>
  <!-- //#overlay -->

・サムネイルclick

myslide_modal.js
//サムネイルクリック
  let point,imgNum;
  $('#thumb li').on('click',function(){
    //連打クリック禁止
    if(click == true){
      click = false;
      point = $('#thumb li').index(this);
      //クリックした場所を検索
      $(this).addClass('act').siblings().removeClass('act');
      imgNum = $('#thumb li').eq(point);
      $('img',panelImg).attr('src',$('img',imgNum).attr('src'));
      $('#modal_contents').html($('.modal_text',imgNum).html());
      $('#overlay').stop().fadeIn(800,
      function(){
        click = true;
      });
      navChange();
    }
  });

  //閉じる
  $('#close_modal').on('click',function(){
    $('#overlay').stop().fadeOut(600);
  });

ソースはGithabにアップしています
https://github.com/mugikomugi/my_slide


まだまだ需要がありそうなスライドショー。
お得意様からオーソドックスなスタイルを要求されることもあったので
そんな時のためにストックとして保存しておくことにしました。
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1