こんにちは。
今回はJavaScriptを使ってスライドショーを作っていきます。
完成版
サムネイルの画像をクリックしたらメイン画像が切り替わり、「<」、「>」ボタンをクリッタしたらその画像を、そして「Play」を押したら自動再生し、「Stop」ボタンで止まるという仕様です。
メイン画像の上には、画像の色の名前を、下にはカラーコードが入ります。
HTML
いつも通り、細かいCSSとかは飛ばして、HTMLタグはこちらになります。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>スライドショー</title>
<link rel="stylesheet" href="css/styles.css">
</head>
<body>
<div class="container">
<main>
<p class="name"></p> <!-- 色の名前表示エリア -->
<img> <!-- メイン画像 -->
<p class="color"></p> <!-- カラーコード表示エリア -->
</main>
<nav>
<ul>
<li id="play">Play</li> <!-- Playボタン -->
<li id="pause" class="hidden">Pause</li> <!-- Stopボタン -->
<li id="prev"><</li> <!-- 前へボタン -->
<li id="next">></li> <!-- 次へボタン -->
</ul>
</nav>
<ul class="thumbnails"></ul> <!-- サムネイル表示エリア -->
</div>
<script src="js/main.js"></script>
</body>
</html>
ではJavaScriptを書いていきます。
配列を作ってメイン画像を表示する
ではまず表示させる画像を配列にします。
各画像には、画像のURLと色の名前、カラーコードを持っています。
配列名はimages
にでもしておきましょう。
let images = [
{url: 'img/pic00.jpg', txt: {name: '紺瑠璃', color: '#164a84'},},
{url: 'img/pic01.jpg', txt: {name: '天色', color: '#2ca9e1'},},
{url: 'img/pic02.jpg', txt: {name: '翡翠色', color: '#38b48b'},},
{url: 'img/pic03.jpg', txt: {name: '浅緑', color: '#88cb7f'},},
{url: 'img/pic04.jpg', txt: {name: '萌黄', color: '#aacf53'},},
{url: 'img/pic05.jpg', txt: {name: '山吹茶', color: '#c89932'},},
{url: 'img/pic06.jpg', txt: {name: '一斤染', color: '#f5b199'},},
{url: 'img/pic07.jpg', txt: {name: '浅蘇芳', color: '#a25768'},},
]
そして今何番目の画像を表示しているかを管理するため、currentNum
を用意し、デフォルトを0にしておきましょう。
そしてとりあえず0番をメインに表示させます。
let currentNum = 0; // 今何番目の画像を表示しているか
ddocument.querySelector('main img').src = images[currentNum].url; // メイン画像を表示
はい、では次はサムネイルです。
サムネイルを表示する
サムネイルはメイン画像の下、<ul class="thumbnails">
の中に<li>
要素ごと作って並べます。
まずは要素の取得です。
const thumbnails = document.querySelector('.thumbnails'); // thumbnails要素の取得
そして、これに対し配列images
の数だけループを回して要素を生成していきます。
生成する要素は<li>
と<img>
です。
const thumbnails = document.querySelector('.thumbnails');
images.forEach(image => { // 配列のループ
const li = document.createElement('li'); // <li>要素を生成
const img = document.createElement('img'); // <img>要素を生成
img.src = image.url; // 生成した<img>のsrc属性に、各要素の値をセットする
li.appendChild(img); // その<img>を<li>の子要素として
thumbnails.appendChild(li); // その<li>をthumbnailsnの子要素として追加する
});
ひとまずこれでサムネイルが表示されます。
そして、今何番の画像を表示しているかというのをわかりやすくするため、currentクラスを<li>
につけていくために、forEachの引数にindexを追加します。
それを使って、もしindexがcurrrentNumと同じだったら、要素にcurrentクラスを追加するというif文も書きましょう。
const thumbnails = document.querySelector('.thumbnails');
images.forEach((image, index) => { // インデックスを追加
const li = document.createElement('li');
if (index === currentNum) { // indexがcurrrentNumと同じだったら
li.classList.add('current'); // currentクラスを追加する
}
const img = document.createElement('img');
img.src = image.url;
li.appendChild(img);
thumbnails.appendChild(li);
});
これでひとまずOKです。
サムネイルをクリックしたらメイン画像も切り替える
生成した<li>
要素にクリックイベントを追加して、メイン画像を切り替えます。
その処理はsetMainImage
として別の関数としてまとめましょう。
その際の引数はimage
として渡します。
images.forEach((image, index) => {
const li = document.createElement('li');
if (index === currentNum) {
li.classList.add('current');
}
li.addEventListener('click', () => {
setMainImage(image); // メイン画像切り替え関数呼び出し
});
const img = document.createElement('img');
img.src = image.url;
li.appendChild(img);
thumbnails.appendChild(li);
});
setMainImage
関数は上記より上に書きましょう。
function setMainImage(image) { // メイン画像切り替え関数
document.querySelector('main img').src = image.url; // 受け取ったimageで書き換える
});
document.querySelector('main img').src = images[currentNum].url;
ここでよく見ると、今作った関数は最初に書いたメイン画像セットの処理にも使えるので以下のようにしましょう。
function setMainImage(image) {
document.querySelector('main img').src = image.url;
});
setMainImage(images[currentNum]); // setMainImageを使って書き換える
ここで書き換える際につまづいたところを書きます。
ミスしたところ
前:document.querySelector('main img').src = images[currentNum].url;
なんだから
後:setMainImage(images[currentNum].url);
だろうと、何も考えずに.url
をつけてしまってエラー出てしまいました。
setMainImage関数の中で.src
に対して.url
をセットしているので、呼び出す際には必要ないんですよね。
呼び出す側は引数として今何番目のインデックスだけ渡せば、setMainImage関数の中で処理するようになっている。私はこういうミスをしがちなので、気をつけたいです。
メイン画像に付随した文言を表示させる
配列を見たとおり、画像のURLだけでなく、オブジェクト化されたデータが入っています。
それを表示させましょう。
各要素を取得し、表示させます。
const name = document.getElementsByClassName('name'); // name要素を取得
const color= document.getElementsByClassName('color'); // color要素を取得
function setMainImage(image) {
document.querySelector('main img').src = image.url;
document.querySelector('main .name').textContent = `${image['txt'].name}`; // nameを表示
document.querySelector('main .color').innerHTML = `カラーコード:<strong>${image['txt'].color}</strong>`; // カラーコードを表示
}
ここでtextContent
とinnerHTML
の違いについて説明します。
簡単に言うと、htmlタグの処理の違いです。前者はタグを書いてもそのままテキストとして表示され、後者はhtmlタグとして反映されます。
今回<strong>
を使いたかったので、カラーコードはinnerHTML
を使いました。
また、innerText
というものも存在します。これもtextContent
同様、タグをそのまま文言として表示します。
違いはあるのですが、それほど気にせずに使っています。詳しく知りたい方は調べていただけるとたくさん出てくると思います。
カレントを移動させる
カレントクラスをつけたり外したりする処理を書きます。
では、まずどのようなタイミングでその処理が発生するか考えると、クリックした時になります。
なので、image.forEach
内のclickイベント内にその処理を追記しましょう。具体的には
1.カレントクラスを外す
2.カレントナンバーを更新する
3.カレントクラスを追加する
です。
li.addEventListener('click', () => {
setMainImage(image);
removeCurremtClass(); // カレントクラスを外す関数
currentNum = index; // カレントナンバーを更新する
addCurremtClass(); // カレントクラスを追加する関数
});
このように書いて、removeCurremtClass関数とaddCurremtClass関数を別に用意しましょう。
function removeCurremtClass() { // カレントクラスを外す関数
document.querySelectorAll('.thumbnails li')[currentNum] // 現在のcurrentNum番目の<li>から
.classList.remove('current'); // currentクラスを外す
}
function addCurremtClass() { // カレントクラスを追加する関数
document.querySelectorAll('.thumbnails li')[currentNum] // 新しいcurrentNum番目の<li>に
.classList.add('current'); // currentクラスを追加する
}
以上で、選択されているサムネイルをカレントクラスにすることができました。
少し長くなってきたので、その2に移動します。https://qiita.com/amanomunt/items/79e331764d817ac33638
ここまでのコード
'use strict';
{
let images = [
{url: 'img/pic00.jpg', txt: {name: '紺瑠璃', color: '#164a84'},},
{url: 'img/pic01.jpg', txt: {name: '天色', color: '#2ca9e1'},},
{url: 'img/pic02.jpg', txt: {name: '翡翠色', color: '#38b48b'},},
{url: 'img/pic03.jpg', txt: {name: '浅緑', color: '#88cb7f'},},
{url: 'img/pic04.jpg', txt: {name: '萌黄', color: '#aacf53'},},
{url: 'img/pic05.jpg', txt: {name: '山吹茶', color: '#c89932'},},
{url: 'img/pic06.jpg', txt: {name: '一斤染', color: '#f5b199'},},
{url: 'img/pic07.jpg', txt: {name: '浅蘇芳', color: '#a25768'},},
]
let currentNum = 0;
const name = document.getElementsByClassName('name');
const color= document.getElementsByClassName('color');
function setMainImage(image) {
document.querySelector('main img').src = image.url;
document.querySelector('main .name').textContent = `${image['txt'].name}`;
document.querySelector('main .color').innerHTML = `カラーコード:<strong>${image['txt'].color}</strong>`;
}
setMainImage(images[currentNum]);
function removeCurremtClass() {
document.querySelectorAll('.thumbnails li')[currentNum].classList.remove('current');
}
function addCurremtClass() {
document.querySelectorAll('.thumbnails li')[currentNum].classList.add('current');
}
const thumbnails = document.querySelector('.thumbnails');
images.forEach((image, index) => {
const li = document.createElement('li');
if (index === currentNum) {
li.classList.add('current');
}
li.addEventListener('click', () => {
setMainImage(image);
removeCurremtClass();
currentNum = index;
addCurremtClass();
});
const img = document.createElement('img');
img.src = image.url;
li.appendChild(img);
thumbnails.appendChild(li);
});
}