課題: 画像ギャラリー
この課題では、多くのウェブサイトでよく見かける、JavaScript を使った画像ギャラリーを作成してもらいます。その過程で、ループ、関数、条件分岐、イベント、DOM スクリプティング、およびオブジェクトの基礎に関する知識が試されます。
出発点
始めるには、下記コードサンプルパネルにある Play ボタンをクリックし、提供された本文テキストを MDN Playground で開いてください。プロジェクト概要の節の手順に従い、JavaScript の機能を完成させてください。
HTML は次のようになります。
<h1>画像ギャラリーの例</h1>
<div class="full-img">
<img
class="displayed-img"
src="https://mdn.github.io/shared-assets/images/examples/learn/gallery/pic1.jpg"
alt="人間の目の拡大" />
<div class="overlay"></div>
<button class="dark">暗く</button>
</div>
<div class="thumb-bar"></div>
出発点の JavaScript はこのようになります。
const displayedImage = document.querySelector(".displayed-img");
const thumbBar = document.querySelector(".thumb-bar");
const btn = document.querySelector("button");
const overlay = document.querySelector(".overlay");
簡潔にするため、このギャラリーの CSS は非表示にしていますが、このアプリを MDN Playground を表示すると見ることができます。
プロジェクト概要
HTML と CSS と数行の JavaScript コードが提供されています。以下の指示に従い、これらを実際に動作する画像ギャラリーにするために必要な JavaScript を記述してください。
ギャラリーは、大きな画像とサムネイルの列で構成されます。サムネイルをクリックするか、タブキーで移動して Enter/Return キーを押すと、そのサムネイルが大きな画像として表示されるようになります。また、該当する <img> 要素も、alt テキストを正しく更新する必要があります。
左上隅にはボタンがあり、これを繰り返し押すと、大きな画像の上に重ねられた <div> 要素の透明度を変更することで、画像の色調を暗い色と明るい色の間で切り替えることができます。
例文に埋め込む必要のある画像と、必要な alt テキストは次のとおりです。
データオブジェクトの作成
まず、images という名前のオブジェクトの配列を宣言していただきます。各オブジェクトには、次の 2 つのプロパティを含める必要があります。
filename: 画像ファイルの名前(完全 URL ではありません)。alt: 画像のaltテキスト。
画像をサムネイルバーに追加
次に、images をループ処理し、DOM スクリプトを使用して、<img> 要素を介してそれらをすべてページに埋め込んでください。これらは、thumbBar 定数ですでに参照している、クラス名 thumb-bar の <div> 要素の子要素として配置する必要があります。
baseURLという名前の定数を作成し、各画像ファイルのベース URL(ファイル名を除いた URL 全体)を格納します。for ... ofループを作成し、imagesの中をループ処理します。- それぞれの画像に対して、新しい
<img>要素を作成します。 <img>のソースを画像の URL と等しくなるように設定します。これはbaseURLとfilenameの組み合わせとします。さらに、alt属性がaltテキストと等しくなるようにします。- もう一つ属性を追加して、
<img>がキーボードからフォーカス設定できるようにします。 - その
<img>をthumbBarに追加します。 clickイベントハンドラーを<img>に追加し、クリックされたときにupdateDisplayedImage()という関数が実行され、クリックされた画像がフルサイズで表示されるようにします。この関数は後で作成します。- この
<img>に、もう 1 つイベントハンドラーを追加します。これにより、キーボードでフォーカスが移動した後、Enter/Return キー(他のキーは除く)を押すことで、クリックされた画像をフルサイズで表示できるようにします。これは、実現には少し調査が必要な追加目標です。
updateDisplayedImage() 関数の作成
それでは、選択されたサムネイルをフルサイズで表示する関数を作成しましょう。フルサイズの <img> 要素への参照は、displayedImage という定数に格納されています。
updateDisplayedImage()関数を定義します。- 関数本体内で、
displayedImageのソースを、アクティブになった<img>のソースと同じに設定します。 displayedImageの代替テキストを、アクティブになった<img>の代替テキストと同じに設定します。
暗く/明るくボタンに配線する
「暗く/明るく」の <button> への参照を btn 定数に、フルサイズの <img> の上に重ねた透明な <div> への参照を overlay 定数に保存しました。以下の作業を行ってください。
clickイベントハンドラーを<button>に追加し、ハンドラー関数として無名関数を設定します。- 関数本体の中で、
<button>要素のclass属性にdarkが設定されているかどうかを判定する条件分岐を追加してください。 - クリックされた時に
<button>要素のclassがdarkになっている場合、そのテキストコンテンツを明るくに変更し、overlay要素の背景色をrgb(0 0 0 / 0.5)に変更します。その後、<button>要素のdarkクラスを削除します。 - クリックされた時に
<button>要素のclass属性にdarkが設定されていない場合、そのテキストコンテンツを暗くに変更し、overlay要素の背景色をrgb(0 0 0 / 0)に変更してください。また、<button>要素にdarkクラスを追加してください。 - 条件分岐の後に、たった 1 行のコードを実行して
darkクラスを切り替える方法は分かりますか?これもまた、少し難易度の高い目標ですが、ぜひ挑戦してみてください。
ヒントとコツ
- HTML と CSS は全く編集する必要はありません。
例
完成したアプリは、次のライブ例のように動作するはずです。
ここをクリックすると、模範解答を表示します。
完成した JavaScript はこのようになるはずです。
const displayedImage = document.querySelector(".displayed-img");
const thumbBar = document.querySelector(".thumb-bar");
const btn = document.querySelector("button");
const overlay = document.querySelector(".overlay");
// 模範解答: データオブジェクトの作成
const images = [
{ filename: "pic1.jpg", alt: "人間の目のクローズアップ" },
{ filename: "pic2.jpg", alt: "波のような岩" },
{ filename: "pic3.jpg", alt: "紫と白のパンジー" },
{ filename: "pic4.jpg", alt: "ファラオの墓にある壁画" },
{ filename: "pic5.jpg", alt: "葉の上の大きな蛾" },
];
// 模範解答: すべての画像を反復処理
// 画像のベース URL を含む baseURL 定数を作成
const baseURL =
"https://mdn.github.io/shared-assets/images/examples/learn/gallery/";
// for...of ループを使用してすべての画像を反復処理
for (const image of images) {
// 新しい画像要素を作成
const newImage = document.createElement("img");
// その画像のソースと代替テキストを設定
newImage.src = `${baseURL}${image.filename}`;
newImage.alt = image.alt;
// 画像をキーボードからフォーカス設定できるようにする
newImage.tabIndex = "0";
// 画像を thumbBar の子として追加
thumbBar.appendChild(newImage);
// サムネイルをクリックした際に、画像をフルサイズで表示するように画面を更新
newImage.addEventListener("click", updateDisplayedImage);
// フォーカスが当たった状態で "Enter" キーが押された際、
// 画像をフルサイズで表示するように画面を更新
newImage.addEventListener("keydown", (e) => {
if (e.code === "Enter") {
updateDisplayedImage(e);
}
});
}
// 模範解答: updateDisplayedImage() 関数の作成
function updateDisplayedImage(e) {
displayedImage.src = e.target.src;
displayedImage.alt = e.target.alt;
}
// 模範解答: 暗く/明るくボタンに配線する
// ボタンに click イベントリスナーを追加
btn.addEventListener("click", () => {
// ボタンに "dark" クラスが設定されていたら、
// テキストを "明るく" に変更してオーバーレイを暗くする
if (btn.classList.contains("dark")) {
btn.textContent = "明るく";
overlay.style.backgroundColor = "rgb(0 0 0 / 0.5)";
} else {
// 送電返れば、テキストを "暗く" に変更して
// オーバーレイを明るくする
btn.textContent = "暗く";
overlay.style.backgroundColor = "rgb(0 0 0 / 0)";
}
// 次のボタンが押される準備としてクラスを切り替える
btn.classList.toggle("dark");
});