今回はjQueryを使わず、素のJavaScriptのみで簡単なスライダーを実装してみます。
普段jQueryを使っている方もDOM操作に慣れていれば割と簡単に作れるのではないでしょうか。
まずはデモを見てみましょう。
以下コードです。
HTML
<div class="slider">
<img id="view" src="img/slider01.jpg">
<i id="prev" class="fas fa-arrow-circle-left"></i>
<i id="next" class="fas fa-arrow-circle-right"></i>
</div>
<nav class="thumbnail">
<ul id="thumbnailList">
</ul>
</nav>
こちらはとてもシンプルです。
スライダー本体と切り替えボタン、クリックして画像を切り替えるためのサムネイル画像の2つのみです。
画像を切り替えるボタンのアイコンはFontawesomeであらかじめ読み込んでおきましょう。
CSS
.slider {
position: relative;
}
.slider img {
width: 100%;
vertical-align: bottom;
backface-visibility: hidden;
-webkit-backface-visibility: hidden;
}
.appear {
animation: fadeIn 2s ease 0s 1 normal;
-webkit-animation: fadeIn 2s ease 0s 1 normal;
backface-visibility: hidden;
-webkit-backface-visibility: hidden;
}
@keyframes fadeIn {
0% {
opacity: 0.2
}
100% {
opacity: 1
}
}
@-webkit-keyframes fadeIn {
0% {
opacity: 0.2
}
100% {
opacity: 1
}
}
.slider i.fas {
color: rgba(25, 25, 25, 0.7);
font-size: 2.5em;
position: absolute;
top: 50%;
bottom: 50%;
}
.slider i.fa-arrow-circle-right {
right: 2%;
}
.slider i.fa-arrow-circle-left {
left: 2%;
}
.thumbnail ul {
margin: 0;
padding: 0;
list-style: none;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-flow: row wrap;
flex-flow: row wrap;
}
.thumbnail ul li {
margin: 10px 0;
width: 23.5%;
margin-right: 2%;
cursor: pointer;
-webkit-filter: grayscale(90%);
filter: grayscale(90%);
}
.thumbnail ul li:nth-child(4n) {
margin-right: 0;
}
.thumbnail ul li:hover {
-webkit-filter: grayscale(0%);
filter: grayscale(0%);
}
.thumbnail ul li.selected {
-webkit-filter: grayscale(0%);
filter: grayscale(0%);
}
.thumbnail ul li img {
width: 100%;
}
こちらも簡単です。
画像がフワッと現れるフェードインはCSSアニメーションで実装しています。
fadeInというアニメーションのキーフレームを作っておいて、
とりあえずappearというクラスに入れておきます。
サムネイル画像は一列に4枚配置で、枚数が増えたら下に回り込むように設定します。
width:23.5%×4枚、margin-right:2%×3で合計100%になります。これで横一列に収まります。
nth-child(4n)で4の倍数のli要素のmargin-rightは0にします。
画像の枚数を増やして下に新しい列ができても、一番右の画像は永遠に4の倍数のli要素となるので右に余白ができなくなります。
サムネイル画像の枚数を変更したいときはこの辺りを変更すればOKですね。
最後にJS
(function () {
const setImage = [
"img/slider01.jpg",
"img/slider02.jpg",
"img/slider03.jpg",
"img/slider04.jpg"
];
const view = document.getElementById('view');
const prev = document.getElementById('prev');
const next = document.getElementById('next');
const thumbnailList = document.getElementById('thumbnailList');
let list;
let image;
let current = 0;
let clickBtn = true;
function createThumbnailItem() {
for (let i = 0; i < setImage.length; i++) {
list = document.createElement('li');
image = document.createElement('img');
image.src = setImage[i];
list.appendChild(image);
thumbnailList.appendChild(list);
if (i === 0) {
list.classList.add("selected");
}
list.addEventListener('click', function () {
view.src = this.children[0].src;
for (let j = 0; j < thumbnailList.children.length; j++) {
thumbnailList.children[j].classList.remove("selected");
};
this.classList.add("selected");
let currentImage = this.children[0].src.slice(-6, -4);
current = Number(currentImage) - 1;
});
};
}
createThumbnailItem();
prev.addEventListener('click', function () {
if (clickBtn === true) {
clickBtn = false;
view.classList.add("appear");
thumbnailList.children[current].classList.remove("selected");
current--;
if (current < 0) {
current = setImage.length - 1;
}
view.src = setImage[current];
thumbnailList.children[current].classList.add("selected");
setTimeout('view.classList.remove("appear");', 2100);
setTimeout(function () {
clickBtn = true;
}, 2100);
} else {
return false;
}
});
next.addEventListener('click', function () {
if (clickBtn === true) {
clickBtn = false;
view.classList.add("appear");
thumbnailList.children[current].classList.remove("selected");
current++;
if (current > setImage.length - 1) {
current = 0;
}
view.src = setImage[current];
thumbnailList.children[current].classList.add("selected");
setTimeout('view.classList.remove("appear");', 2100);
setTimeout(function () {
clickBtn = true;
}, 2100);
} else {
return false;
}
});
function autoPlay() {
setTimeout(function () {
next.click();
autoPlay();
}, 5000);
}
window.onload = autoPlay();
})();
こちらも簡単ですが、ちょっとだけ長いですね。
順に説明していきます。
const setImage = [
"img/slider01.jpg",
"img/slider02.jpg",
"img/slider03.jpg",
"img/slider04.jpg"
];
const view = document.getElementById('view');
const prev = document.getElementById('prev');
const next = document.getElementById('next');
const thumbnailList = document.getElementById('thumbnailList');
let list;
let image;
let current = 0;
let clickBtn = true;
まず色々と変数を定義していきます。
setImageにはスライダーとサムネイルに表示する画像を配列で代入していきます。
listやimageはulタグの中にサムネイル画像を作成する際に使用します。
currentは現在表示されている画像のインデックス番号だと思ってください。
clickBtnは連続クリックを防ぐためにボタンのイベント処理に使用します。
function createThumbnailItem() {
for (let i = 0; i < setImage.length; i++) {
list = document.createElement('li');
image = document.createElement('img');
image.src = setImage[i];
list.appendChild(image);
thumbnailList.appendChild(list);
if (i === 0) {
list.classList.add("selected");
}
list.addEventListener('click', function () {
view.src = this.children[0].src;
for (let j = 0; j < thumbnailList.children.length; j++) {
thumbnailList.children[j].classList.remove("selected");
};
this.classList.add("selected");
let currentImage = this.children[0].src.slice(-6, -4);
current = Number(currentImage) - 1;
});
};
}
createThumbnailItem();
上記のHTMLではulタグの中身が空なので、JavaScriptでulタグの中身にサムネイルを作成していきます。
スライドショーに現在表示されている画像のサムネイルはselectedというクラスを付けて画像を明るくします。
if文を使ってデフォルトで一番最初のサムネイル画像にselectedをつけておきます。
クリック処理の中では、選択されたサムネイルのsrc属性を
スライドショーのimgタグのsrc属性に代入しています。
また、この時にselectedクラスを移動させる必要があるので、
一旦サムネイル画像のselectedクラスを消して、
クリックしたサムネイル画像にselectedクラスを追加しています。
そして最後に、サムネイル画像のsrc属性をsliceを使って番号のみ切り出します。
切り出した段階では文字型になっているので、Numberオブジェクトを使って数値型に戻した後に、
現在表示されている画像の番号として変数currentに代入してあげます。
この変数currentは、スライドショー上の次へボタンと前へ戻るボタンとサムネイル画像を紐づけるためにも使用します。
-1を引いているのはまたあとで説明します。
prev.addEventListener('click', function () {
if (clickBtn === true) {
clickBtn = false;
view.classList.add("appear");
thumbnailList.children[current].classList.remove("selected");
current--;
if (current < 0) {
current = setImage.length - 1;
}
view.src = setImage[current];
thumbnailList.children[current].classList.add("selected");
setTimeout('view.classList.remove("appear");', 2100);
setTimeout(function () {
clickBtn = true;
}, 2100);
} else {
return false;
}
});
next.addEventListener('click', function () {
if (clickBtn === true) {
clickBtn = false;
view.classList.add("appear");
thumbnailList.children[current].classList.remove("selected");
current++;
if (current > setImage.length - 1) {
current = 0;
}
view.src = setImage[current];
thumbnailList.children[current].classList.add("selected");
setTimeout('view.classList.remove("appear");', 2100);
setTimeout(function () {
clickBtn = true;
}, 2100);
} else {
return false;
}
});
function autoPlay() {
setTimeout(function () {
next.click();
autoPlay();
}, 5000);
}
window.onload = autoPlay();
ここではボタンに関するクリックイベントを定義しています。
前へボタンをクリックしたらcurrentに-1、次へボタンをクリックしたらcurrentに+1を足し算していきます。
そして、このcurrentをインデックス番号として変数setImageの配列からcurrentのインデックス番号の画像を取り出したのち、
スライドショーのsrc属性に代入してあげます。
currentの数値が画像の枚数より多くなったり、0より小さくなったりしないようにif文で分岐します。
変数setImage.lengthから-1を引いているのは、currentの初期値は0から数えられ、setImage.lengthは1から数えられるためです。
ここで整合性を合わせるためにsetImage.lengthから-1を引いています。
先ほどのサムネイル画像のクリックイベントの時もこれと同じ理論です。
クリックの際のアニメーションに関しては、スライドショーのクラスにappearというクラスを追加しています。
このappearクラスには先ほどcssで設定したフェードインのアニメーションが内包されています。
アニメーションの秒数は2秒で設定しているので、2.1秒経過したあとにこのクラスをsetTimeoutで外すよう命令をかけています。
これでクリックするたびに、フェードインのアニメーションがかかるようになります。
最後にif文で囲ってあげて、clickBtnの真偽地がtrueの時だけクリックできるようにし、
falseの時はなにも起きないようにしてあげます。
これはアニメーションが終わる前の連続クリックを防ぐためです。
最後に自動再生です。
これは簡単で、ひたすら次へボタンを5秒ごとにクリックする処理をsetTimeout関数で処理してあげればOKです。
ページが読み込まれたら自動再生するように、window.onloadに代入してあげます。
まとめ
jQueryは直観的な操作で学習コストが低い反面、素のJavaScriptに比べて重くなりがちという難点があります。
他にも、jQueryだけに慣れていると、他サイトを研究する際に複雑なJavaScriptは読めなくて苦労したり、カスタマイズの自由性に劣ったりします。
両方できるのが一番だと思いますので、jQueryに慣れてきたら是非JavaScriptにもチャレンジしてみてください。