こんにちは、ユイトです(@mikiprogram)
画像やコンテンツを左右に切り替えるスライダーをshibajukuで学習しました。
学習のアウトプットとして記事に残していきます。
機能紹介
今回作成するスライダーの機能を紹介します。
- 「次へ」ボタンを押すとスライドして次の画像を表示
- 「前へ」ボタンを押すとスライドして前の画像を表示
では、早速作っていきます!
完成コード
タブメニューになっているので切り替えると、CSS・jQueryのコードが表示されます。
完成コードはこちらです↓
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>コンテンツスライダー①</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="l-container">
<h1 class="m-pageTitle">コンテンツスライダー①</h1>
<div class="m-sliderWrap">
<ul class="m-slider" id="js-slider">
<li class="js-sliderItem m-slider__item">
<img src="images/grape.jpg" alt="ぶどう" />
</li>
<li class="js-sliderItem m-slider__item">
<img src="images/apple.jpg" alt="りんご" />
</li>
<li class="js-sliderItem m-slider__item">
<img src="images/lemon.jpg" alt="レモン" />
</li>
<li class="js-sliderItem m-slider__item">
<img src="images/pineapple.jpg" alt="パイナップル" />
</li>
<li class="js-sliderItem m-slider__item">
<img src="images/strawberry.jpg" alt="いちご" />
</li>
</ul>
</div>
<!-- /.m-sliderWrap -->
<ul class="m-sliderNav">
<li class="m-sliderNav__item">
<button class="m-button --prev" id="js-sliderPrevButton">前へ</button>
</li>
<li class="m-sliderNav__item">
<button class="m-button --next" id="js-sliderNextButton">次へ</button>
</li>
</ul>
</div>
<!-- /.l-container -->
<script
src="https://code.jquery.com/jquery-1.12.4.min.js"
integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ="
crossorigin="anonymous"
></script>
<script src="app.js"></script>
</body>
</html>
CodeSandBoxで簡単なデモページを作成しました!
※レスポンシブには対応していないので、恐れ入りますがPCからご覧ください。
HTML作成
スライドするためのコンテンツと、「前へ」・「次へ」ボタンを作成します。
<div class="l-container">
<h1>コンテンツスライダー</h1>
<div class="m-sliderWrap">
<ul class="m-slider">
<li class="m-slider__item">
<img src="images/grape.jpg" alt="ぶどう">
</li>
<li class="m-slider__item">
<img src="apple.jpg" alt="りんご">
</li>
<li class="m-slider__item">
<img src="images/lemon.jpg" alt="レモン">
</li>
<li class="js-sliderItem m-slider__item">
<img src="images/pineapple.jpg" alt="パイナップル" />
</li>
<li class="js-sliderItem m-slider__item">
<img src="images/strawberry.jpg" alt="いちご" />
</li>
</ul>
</div>
<!-- /.m-sliderWrap -->
<ul>
<li><button>前へ</button></li>
<li><button>次へ</button></li>
</ul>
</div>
<!-- /.l-container -->
a要素とbutton要素の使い分け
・別のページにジャンプする機能が必要なときは、a
要素を使用します。
・表示・非表示を切り替えるときは、button
要素を使用します。
※個人的な使い分けの考えです。
スライドするコンテンツを横並び
主に、以下の3点をCSSで書いていきます。
l-container
にwidth:1000px;
、margin: 3em auto;
を指定して中央揃えにします。
m-slider
にdisplay:flex;
でスライドするコンテンツを横並びにします。
また、画像の合計枚数分のwidth
を指定します。
m-sliderWrap
に、overflow:hidden;
で
見た目上、画像一枚分しか表示できないようにします。
.l-container {
width: 1000px;
margin: 3em auto;
}
.m-sliderWrap {
overflow: hidden;
/* 親要素である.l-containerの幅が800pxのため、widthを指定する必要なし */
}
.m-slider {
display: flex;
/* スライドする画像の合計幅を指定 */
width: 3000px;
}
m-sliderWrap
のwidth
について
width
に関しては、親要素のl-container
の幅が1000px
のため、指定しなくても良いです。
理由は、ブロックレベル要素のwidth
は初期値がauto
だからです。
スライドの仕組みをイメージする
画像をスライドさせる方法として、position
プロパティを使用します。
m-slider
にposition:relative;
を指定し、
画像一枚分の幅をleft
に指定すると、二番目の画像が表示されます。
また、画像二枚分の幅をleft
に指定すると三番目の画像が表示されます。
今回は、この動きを「前へ」・「次へ」ボタンをクリックしたときに動的に行うため、
JavaScriptを記述していきます。
.m-slider {
//相対配置
position: relative;
//画像一枚分右に移動して2番目の画像が表示される
left: -1000px;
display: flex;
width: 3000px;
}
スライドのイメージ動画はこちら↓
※右下でleft
の値を調整しています。
「前へ」・「次へ」ボタンのクリックイベント作成
JavaScriptで操作する用のid属性をHTMLに追加
追加する要素は以下の3点です。
ul
要素にid属性js-slider
を追加します。
- 「前へ」の
button
要素にid属性js-sliderPrevButton
を追加します。
- 「次へ」の
button
要素にid属性js-sliderNextButon
を追加します。
<div class="l-container">
<h1 class="m-pageTitle">コンテンツスライダー</h1>
<div class="m-sliderWrap">
<ul class="m-slider" id="js-slider">
<!-- 中身省略 -->
</ul>
</div>
<!-- /.m-sliderWrap -->
<!-- 省略 -->
</div>
<!-- /.l-container -->
現在何枚目の画像を表示しているかを管理するための変数を作成
「現在何枚目の画像を表示しているか」管理するためのコンテンツ番号、変数indexに0を代入します。
$(function() {
//現在のコンテンツ番号を管理
var index = 0;
});
「前へ」ボタンのクリックイベントを作成
まず、「前へ」ボタンをクリックするたびに、コンテンツ番号から1を引きます。
次に、js-slider
のleft
の値をanimate()
を使って変更します。
また、アニメーションを実行中にボタンを素早くクリックすると、
クリックした回数分だけアニメーションが継続されるので
アニメーションを止めるために、animate()
の前にstop()
を使用します。
$(function () {
var index = 0;
//「前へ」ボタンをクリックした時の処理
$("#js-sliderPrevButton").click(function() {
//現在のコンテンツ番号から1を引く
index -- ;
//leftの値をアニメーションで変更
$("#js-slider").stop().animate({
left: "-1000" * index
},300);
});
};
「次へ」ボタンのクリックイベントを作成
まず、「次へ」ボタンをクリックするたびに、コンテンツ番号から1を足します。
それ以降の処理は、「前へ」ボタンと一緒です。
$(function () {
var index = 0;
$("#js-sliderPrevButton").click(function() {
index -- ;
$("#js-slider").animate({
left: "-1000" * index
},300);
});
//「次へ」ボタンをクリックした時の処理
$("#js-sliderNextButton").click(function() {
//現在のコンテン番号に1を足す
index ++ ;
//leftの値をアニメーションで変更
$("#js-slider").stop().animate({
left: "-1000" * index
},300);
});
};
この時点で、
「次へ」ボタンを押すと、二枚目、三枚目と表示され、
「前へ」ボタンを押すと、三枚目、二枚目と表示され、機能としては完成しています。
しかし、今のままでは「次へ」ボタンを押し続けるとコンテンツが存在しなくても、
js-slider
が移動し続けてしまいます。「前へ」ボタンでも同様です。
そのため、コンテンツ番号を調整して、コンテンツが存在しない場所には
移動させないようにしていきます。
コンテンツが存在しない場所には、移動させない
今のままでは、コンテンツが存在しない場所でも移動できてしまうので、
以下のようにしたいと思います。
- もしも、最初のコンテンツで「前へ」ボタンがクリックされると、
最後のコンテンツに移動させます。
- もしも、最後のコンテンツで「次へ」ボタンがクリックされると、
最初のコンテンツに移動させます。
li要素にJavaScript操作用のclass属性を追加
li
要素にJavaScript操作用のclass属性js-sliderItem
を追加します。
<div class="m-sliderWrap">
<ul class="m-slider" id="js-slider">
<li class="js-sliderItem m-slider__item">
<!-- 省略-->
</li>
<!-- 省略 -->
</ul>
</div>
<!-- /.m-sliderWrap -->
コンテンツの合計数を取得する
コンテンツの数を使って条件分岐を使いたいので、コンテンツの数を取得します。
$(function () {
var index = 0;
//コンテンツの数を取得
var slideCount = $(".js-sliderItem").length;
$("#js-sliderPrevButton").click(function() {
index -- ;
$("#js-slider").stop().animate({
left: "-1000" * index
},300);
});
$("#js-sliderNextButton").click(function() {
index ++ ;
$("#js-slider").stop().animate({
left: "-1000" * index
},300);
});
};
今回のコンテンツの数は、三個なので直接「3」を使って条件分岐できますが、
コンテンツの数が変わったときにメンテナンス性が悪いのでlength
で取得した値を使います。
「前へ」ボタンの条件分岐
最初のコンテンツで「前へ」ボタンがクリックされると、
最後のコンテンツに移動したいので、
「現在のコンテンツ番号が0より小さいとき」のif
文を書いていきます。
そして、0より小さいときは、コンテンツ番号をコンテンツ数から「1」引いた値にします。
$(function () {
var index = 0;
var slideCount = $(".js-sliderItem").length;
$("#js-sliderPrevButton").click(function() {
index -- ;
//コンテンツ番号が0より小さいかチェック
if(index < 0) {
//コンテンツ番号をコンテンツ数から1引いた値にする。
index = slideCount -1;
}
$("#js-slider").stop().animate({
left: "-1000" * index
},300);
});
$("#js-sliderNextButton").click(function() {
index ++ ;
$("#js-slider").stop().animate({
left: "-1000" * index
},300);
});
};
「次へ」ボタンの条件分岐
最後のコンテンツで「次へ」ボタンがクリックされると、
最初のコンテンツに移動に移動したいので、
「コンテンツ番号がコンテンツ数以上のとき」のif
文を書いていきます。
そして、コンテンツ数以上のときは、コンテンツ番号を「0」にします。
$(function () {
var index = 0;
var slideCount = $(".js-sliderItem").length;
$("#js-sliderPrevButton").click(function() {
index -- ;
if(index < 0) {
index = slideCount -1;
}
$("#js-slider").stop().animate({
left: "-1000" * index
},300);
});
$("#js-sliderNextButton").click(function() {
index ++ ;
//コンテンツ番号がコンテンツ数以上のとき
if(index > slideCount - 1) {
//コンテンツ番号を0にする
index = 0;
}
$("#js-slider").stop().animate({
left: "-1000" * index
},300);
});
};
重複している処理を関数化する
以上で今回したかった機能は実現することはできました。
しかし、「次へ」・「前へ」ボタンのクリックイベントを見てみると、animate()
の部分や
if
文は関数にまとめることができそうなので、処理をまとめていきます。
目的のコンテンツまで移動させる独自関数を作成
animate()
の部分は「前へ」・「次へ」ボタンのどちらも同じ処理を行なっているので、
独自関数function sliding(){・・・}
にまとめます。
まとめるだけだと、処理が実行されないのでsliding()
で呼び出して実行します。
$(function () {
var index = 0;
var slideCount = $(".js-sliderItem").length;
//目的のコンテンツまで移動させる独自関数
function sliding() {
$("#js-slider").stop().animate({
left: "-1000" * index
},300);
}
$("#js-sliderPrevButton").click(function() {
index -- ;
if(index < 0) {
index = slideCount -1;
}
//独自関数の呼び出し
sliding();
});
$("#js-sliderNextButton").click(function() {
index ++ ;
if(index > slideCount - 1) {
index = 0;
}
//独自関数の呼び出し
sliding();
});
};
条件分岐をまとめる
「前へ」・「次へ」ボタンのif
文もsliding()
に処理できるので、まとめます。
これ以上関数にまとめることができないので、今回はこれで完成です😄
$(function () {
var index = 0;
var slideCount = $(".js-sliderItem").length;
//目的のコンテンツまで移動させる独自関数
function sliding() {
//if文をまとめる
if(index < 0) {
index = slideCount -1;
}
//if文をまとめる
if(index > slideCount - 1) {
index = 0;
}
$("#js-slider").stop().animate({
left: "-1000" * index
},300);
}
$("#js-sliderPrevButton").click(function() {
index -- ;
sliding();
});
$("#js-sliderNextButton").click(function() {
index ++ ;
sliding();
});
};
まとめ
今回は簡単なスライダーを作成しました。
重複している処理を関数にまとめて、コード量が短くなるとスッキリしていいですね!
次回は、自動でスライドする機能や画像の数が変わっても、
CSSでwidthを調整してなくて良い、メンテナンス性の高いスライダーを作りたいと思います!
最後まで読んでいただきありがとうございました🙇