便利なプラグインがたくさんあるスライドショーですが、できれば自作のものを使いたいと思いjsで開発しました。
ベースを作って自分のストック用として手動、自動、モーダルと1セット揃えました。
この際、逃げ腰だったタッチイベントにも挑戦。
手動スライド
<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を取得します。
サムネをクリックした時、この方が分かりやすいと思ったもので。
・下準備 サイズ設定
//スライド一つ分の長さを取得
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へ付け変わります。
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をマイナス値に。
//前へ
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を非表示に。
ナビが隠れることによってスライドは不可になります。
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と同じです。
//サムネイルクリック
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’以外は何でもいいです。
//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()は無くしてカルーセルにしています。
スワイプ不可の条件文も外しています。
function slideStart(){
nextSlide();
timerID = setTimeout(slideStart, 3000);
}
//タイマー起動
slideStart();
横幅100%自動スライド
ファーストビューでよく見かけるブラウザ幅100%で端が見えているタイプです。
cssはかなり変更しました。
<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メソッドを使います。
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データも格納しました。
<!-- オーバーレイ -->
<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
//サムネイルクリック
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
まだまだ需要がありそうなスライドショー。
お得意様からオーソドックスなスタイルを要求されることもあったので
そんな時のためにストックとして保存しておくことにしました。