繰り返しの処理を使って、クリック(タップ)やマウスオーバーで画像を切り替える、ギャラリーを作成します。
キーワード:配列、繰り返し(forEach)
作成例(完成イメージ)
- 作成例:https://ngsm-syr.github.io/javascript_gallery/
- コード:https://github.com/ngsm-syr/javascript_gallery/
下記の順番で進めます。
- メインイメージを定数にセットする
- サムネイル画像を配列として定数にセットする
- サムネイルがクリックされたときに、メインイメージのsrcを、サムネイル画像のdata-image属性に置き換える、イベントを設定する
- サムネイルの数分、上記の設定が行われるようにする
【準備】フォルダ:javascript_gallery
①JavaScriptを書くための準備で作成したフォルダ(空のHTML、CSS、JavaScriptが入っている)を準備します。GitHubからもダウンロードできます。
②フォルダの名前を「javascript_gallery」に変更します
③同じサイズの画像を3〜8枚程度用意します。作例と同じ画像を使う方は、Githubからダウンロードしてください。
画像は images フォルダに入れます。
HTMLとCSSファイルの準備
まず、コンテンツ部分を用意します。
▼index.html
<header>
<h1>Photo Gallery</h1>
</header>
<main>
<div class="gallery">
<div>
<img src="images/img01.png" id="main-image" alt="img01" title="img01">
</div>
<ul>
<li><img src="images/img01.png" alt="img01" title="img01" class="thumb" data-image="images/img01.png"></li>
<li><img src="images/img02.png" alt="img02" title="img02" class="thumb" data-image="images/img02.png"></li>
<li><img src="images/img03.png" alt="img03" title="img03" class="thumb" data-image="images/img03.png"></li>
</ul>
</div>
</main>
imgタグに含まれる「data-○○ 」はデータ属性と呼ばれ、○○の部分を自分で決めることができます。JavaScriptやCSSを使って取り出すことができます。
今回の場合は「data-image」の部分に、切り替える画像のファイル名を指定しています。srcと同じ内容になっていますが、別の内容にすることもできます。サムネイル用の小さい画像と、大きく表示する画像を別の画像にすることも可能です。
▼style.css
* {
margin: 0;
padding: 0;
vertical-align: bottom;
}
body {
display: grid;
justify-content: center;
}
img {
width: 100%;
height: auto;
}
h1 {
text-align: center;
padding: 10px 0;
}
footer {
text-align: center;
}
.gallery {
max-width: 800px;
padding: 10px;
}
ul {
list-style: none;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
padding-top: 10px;
gap: 10px;
}
*{ }
は、全てのセレクターに対する設定を表しています。ここでは、marginとpaddingを0にすることで、元々各セレクターの持つ、固有の余白をリセットしています。
この作例では、画面の中央揃えや、サムネイルの表示にCSSグリッドを使った設定をしています。
CSSグリッドとは、格子状のマス目をつくり、マス目の上に自由に配置する方法です。タイル状の配置をするときに使用すると、少ないコード数で配置することができます。ローディングアニメーションの作例のような画像配置もグリッドで作成できます。
定数の定義
▼script.js
const main = document.querySelector('#main-image');
const thumbs = document.querySelectorAll('.thumb');
// 確認
console.log(main);
console.log(thumbs);
constを使って、HTMLの要素を定数(箱)に格納しています。
今回は要素の取得にquerySelectorを使っています。
以前の作例で使った、getElementById や getElementsByClassName などは、idか、classか…など種類によって使い分ける必要がありますが、querySelector では、idもclassも一緒に扱うことができます。
CSSでの書き方と同じように「#(idの場合)」「.(classの場合)」で区別できるので、視覚的にもidとclassが区別しやすいです。
1つのみ取得するときは、querySelector、全て取得するときはquerySelectorAllを使います。「.thumb」クラスは、複数ありますので、querySelectorAllを使っています。
- 途中経過:https://ngsm-syr.github.io/javascript_gallery_a/
- コード:https://github.com/ngsm-syr/javascript_gallery_a/
補足:配列
console.log(thumbs);
を使って確認すると、「.thumb」クラスの付いた要素に、連番がついて、順番に取得されていることが確認できます。仕切りのついた箱に一つ一つ入れていくようなイメージです。
定数の箱に仕切りをつけて、複数のものを入れて処理することを、配列といいます。
※ただし、querySelectorAll で取得されるのは、NodeListと呼ばれるもので、正確に言うと配列ではなく「配列風」ですが、後述のforEachを使った繰り返し処理ができます。
下記は配列の例です。
▼console に入力①
const fruits = ['apple','banana','orange'];
console.log( fruits );
配列の要素にはそれぞれ、番号(インデックス)が振られ、番号を指定することで中身を取り出すことができます。
▼console に入力②
const fruits = ['apple','banana','orange'];
console.log( fruits[1] );
インデックスは、0から始まるため、fruits[1] は、appleではなく、banana になります。
繰り返しの処理(配列の要素数分、繰り返す)
▼script.js
// 確認
// console.log(main);
// console.log(thumbs);
thumbs.forEach(function(item, index) {
item.onclick = function() {
console.log(this.dataset.image);
}
});
クリックすると、コンソール上に、dataset-imageの内容が出力されます。
メインイメージのsrc要素をdataset-imageで置き換える
▼script.js
thumbs.forEach(function(item, index) {
item.onclick = function() {
// console.log(this.dataset.image);
main.src = this.dataset.image;
}
});
【応用】マウスオーバーで変化するようにする
クリックではなくマウスオーバーで変化するように、コードを書き換えます
▼script.js
// マウスオーバー
thumbs.forEach(function(item, index) {
item.onmouseover = function() {
main.src = this.dataset.image;
}
});
【応用】イベントリスナーを使って書く
同じ動作をaddEventListener
を使って書くこともできます
//イベントリスナー
thumbs.forEach(function (item, index) {
function change() {
main.src = this.dataset.image;
}
item.addEventListener('mouseover', change);
});
作例は、シンプルな機能のみを使っているので、onを使う書き方(イベントハンドラ)の方がコードが短くなります。イベントリスナーを使った書き方では、イベントを削除したり、複数追加したりできる点で、より複雑な用途にも対応できます。
参考→イベントへの入門(mdn web doc)
【応用】CSSで調整する
hoverの効果
CSSでhover時の効果を追加します
▼style.css(一番下に追加)
ul li img {
transition: opacity .5s;
}
ul li img:hover {
cursor: pointer;
opacity: .7;
}
サムネイル部分にはリンク(<a>
タグ)を使用していないため、マウスをのせてもカーソルが変化しません。クリックできる(反応する)ことがわかるように、カーソルが指の形に変わるように設定しています。
また、opacity
を使って、画像の不透明度を変化させています(transition
の効果で、なめらかに変化)。
レスポンシブ対応
スマホ表示時、1行あたりのサムネイル数を減らす設定を追加します。
適宜、画像も追加してください。3列→2列にするなら6の倍数、4列→2列にするなら、4の倍数の画像数があると収まりがよくなります。
▼style.css(一番下に追加)
@media screen and (max-width: 640px) {
ul {
grid-template-columns: 1fr 1fr;
}
}
この例では、画面が狭いときに、グリッドの分割数を、3列→2列に変更しています。
- 途中経過:https://ngsm-syr.github.io/javascript_gallery_b/
- コード:https://github.com/ngsm-syr/javascript_gallery_b/
【応用】キャプションを表示する
キャプションを表示して、画像の切り替えだけでなく、キャプションも切り替えられるようにします。
▼index.html(メインイメージ部分にキャプションの表示場所を追加)
<div>
<img src="images/img01.png" id="main-image" alt="img01" title="img01">
<p id="caption">img01</p>
</div>
▼style.css(@mediaより前)
.gallery div {
position: relative;
}
#caption {
position: absolute;
bottom: 0;
background: rgba(0, 0, 0, .5);
padding: 10px;
width: 100%;
box-sizing: border-box;
color: #FFF;
}
@media screen and (max-width: 640px) {
中略
▼script.js
const text = document.querySelector('#caption');
//マウスオーバー
thumbs.forEach(function(item, index) {
item.onmouseover = function() {
main.src = this.dataset.image;
text.textContent = this.title;
}
});
タイトル属性に入力されている情報をキャプションとして表示します。
- 作成例:https://ngsm-syr.github.io/javascript_gallery/
- コード:https://github.com/ngsm-syr/javascript_gallery/
参考書籍・リンク
- 「すらすらわかるJavaScript 新版」桜庭洋之,望月幸太郎, 翔泳社,2022
- 「JavaScript「超」入門」狩野祐東,SBクリエイティブ,2019
- 「1冊ですべて身につくJavaScript入門講座」Mana, SBクリエイティブ, 2023
- 「独習JavaScript」CodeMafia 外村将大, 翔泳社, 2021
- https://developer.mozilla.org/ja/docs/Learn/HTML/Howto/Use_data_attributes
- https://developer.mozilla.org/ja/docs/Web/API/Document/querySelectorAll
- https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
- https://developer.mozilla.org/ja/docs/Web/CSS/CSS_grid_layout/Basic_concepts_of_grid_layout
- https://developer.mozilla.org/ja/docs/Web/CSS/grid
- https://developer.mozilla.org/ja/docs/Web/CSS/grid-template-columns
- https://developer.mozilla.org/ja/docs/Learn/JavaScript/Building_blocks/Events