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

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

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

## 手動スライド

[サンプルサイト＞](https://gallery.okamechan.com/slide/touch.html)

```html: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を取得します。
サムネをクリックした時、この方が分かりやすいと思ったもので。

・下準備　サイズ設定
```js: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へ付け変わります。
```js: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をマイナス値に。
```js: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を非表示に。
ナビが隠れることによってスライドは不可になります。
```js: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と同じです。
```js: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’以外は何でもいいです。
```js: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;
    }
```

## 自動スライド

[サンプルサイト＞](https://gallery.okamechan.com/slide/touch_timer.html)

手動スライドにsetTimeoutをつけました。
エンドレスにループさせた為、navChange()は無くしてカルーセルにしています。
スワイプ不可の条件文も外しています。
```js:myslide_timer.js
  function slideStart(){
      nextSlide();
      timerID = setTimeout(slideStart, 3000);
  }
  //タイマー起動
  slideStart();
```

## 横幅100%自動スライド

[サンプルサイト＞](https://gallery.okamechan.com/slide/touch_timer_wide.html)

ファーストビューでよく見かけるブラウザ幅100％で端が見えているタイプです。
cssはかなり変更しました。
```html: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メソッドを使います。
```js: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;
    });
  }
```

## モーダルスライド

[サンプルサイト＞](https://gallery.okamechan.com/slide/touch_modal.html)

モーダルウィンドウが浮かび上がってからattrメソッドで切り替わる仕様です。
サムネイルに画像の他、htmlデータも格納しました。
```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
```js: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);
  });
```

<br>

:::note info
ソースはGithabにアップしています
https://github.com/mugikomugi/my_slide
:::
<br>
まだまだ需要がありそうなスライドショー。<br>
お得意様からオーソドックスなスタイルを要求されることもあったので<br>
そんな時のためにストックとして保存しておくことにしました。