挑战:图片库
在本挑战中,我们将指导您构建一个在许多网站上都能看到的常见项目 — 一个由 JavaScript 驱动的图片库。在此过程中,您将测试您对循环、函数、条件语句、事件、DOM 脚本和对象基础知识的掌握程度。
起始点
首先,点击下方代码面板中的播放按钮,在MDN Playground中打开提供的示例。然后,你将按照项目简介部分中的说明完成JavaScript功能。
HTML 如下所示:
<h1>Image gallery example</h1>
<div class="full-img">
<img
class="displayed-img"
src="https://mdn.github.io/shared-assets/images/examples/learn/gallery/pic1.jpg"
alt="Closeup of a human eye" />
<div class="overlay"></div>
<button class="dark">Darken</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,将其转换为一个可用的图片库。
图片库将由一张大图和一排缩略图组成。当点击或通过 Tab 键聚焦缩略图并按下 Enter/Return 键时,该缩略图应显示为大图。相应的 <img>
元素也应更新为正确的 alt
文本。
左上角有一个按钮,反复按下该按钮可以切换大图在较暗和较亮色调之间的显示效果,这是通过更改覆盖在大图上方的 <div>
元素的透明度来实现的。
您需要在示例中嵌入的图片及其所需的 alt
文本如下:
创建一个数据对象
首先,我们希望您声明一个名为 images
的对象数组。每个对象应包含两个属性:
filename
:图片文件的名称(不是完整 URL)。alt
:图片的alt
文本。
将图片添加到缩略图栏
接下来,我们希望您循环遍历 images
数组,并使用一些 DOM 脚本通过 <img>
元素将它们全部嵌入到页面中。它们应作为类名为 thumb-bar
的 <div>
元素的子元素包含,我们已经在 thumbBar
常量中引用了它。
- 创建一个名为
baseURL
的常量,其中包含每个图片文件的基本 URL(URL 中不包含文件名部分)。 - 创建一个
for ... of
循环来遍历images
数组。 - 对于每个图片,创建一个新的
<img>
元素。 - 将
<img>
的源设置为图片的 URL,该 URL 应该是baseURL
和filename
的组合;并将alt
属性设置为alt
文本。 - 为
<img>
添加另一个属性,使其可以通过键盘焦点访问。 - 将
<img>
元素追加到thumbBar
。 - 为
<img>
添加一个click
事件处理程序,以便在单击它时,会运行一个名为updateDisplayedImage()
的函数,该函数会将单击的图片以全尺寸显示。您将在稍后创建此函数。 - 为
<img>
添加另一个事件处理程序,以便一旦通过键盘聚焦,就可以通过按 Enter/Return 键(仅此键)来以全尺寸显示单击的图片。这是一个有挑战性的目标,需要一些研究才能弄清楚。
创建 updateDisplayedImage()
函数
现在是时候创建用于以全尺寸显示激活缩略图的函数了。我们已将全尺寸 <img>
元素的引用存储在 displayedImage
常量中。
- 定义
updateDisplayedImage()
函数。 - 在函数体内,将
displayedImage
的源设置为已激活的<img>
元素的源。 - 将
displayedImage
的 alt 文本设置为已激活的<img>
元素的 alt 文本。
连接“变暗/变亮”按钮
我们已将“变暗/变亮” <button>
的引用存储在 btn
常量中,并将覆盖在全尺寸 <img>
上方的透明 <div>
的引用存储在 overlay
常量中。我们希望您:
- 为
<button>
添加一个click
事件处理程序,并将一个匿名函数设置为处理程序函数。 - 在函数体内,添加一个条件结构,测试
<button>
是否具有dark
类。 - 如果
<button>
被点击时具有dark
类,将其文本内容更改为Lighten
,并将overlay
元素的背景颜色更改为rgb(0 0 0 / 0.5)
。移除<button>
元素的dark
类。 - 如果
<button>
被点击时不具有dark
类,将其文本内容更改为Darken
,并将overlay
元素的背景颜色更改为rgb(0 0 0 / 0)
。添加<button>
元素的dark
类。 - 您能否想出一个方法,使用一行代码来切换
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");
// Solution: Create a data object
const images = [
{ filename: "pic1.jpg", alt: "Closeup of a human eye" },
{ filename: "pic2.jpg", alt: "Rock that looks like a wave" },
{ filename: "pic3.jpg", alt: "Purple and white pansies" },
{ filename: "pic4.jpg", alt: "Section of wall from a pharaoh's tomb" },
{ filename: "pic5.jpg", alt: "Large moth on a leaf" },
];
// Solution: Loop through the images
// Create a baseURL constant containing the baseURL of the images
const baseURL =
"https://mdn.github.io/shared-assets/images/examples/learn/gallery/";
// Loop through the images using a for...of loop
for (const image of images) {
// Create a new image element
const newImage = document.createElement("img");
// Set the source and alt text for the image
newImage.src = `${baseURL}${image.filename}`;
newImage.alt = image.alt;
// Make the image focusable via the keyboard
newImage.tabIndex = "0";
// Append the image as a child of the thumbBar
thumbBar.appendChild(newImage);
// Update the display to show the image full size when a thumb is clicked
newImage.addEventListener("click", updateDisplayedImage);
// Update the display to show the image full size when the "Enter" key
// is pressed after it has been focused
newImage.addEventListener("keydown", (e) => {
if (e.code === "Enter") {
updateDisplayedImage(e);
}
});
}
// Solution: Create the updateDisplayedImage() function
function updateDisplayedImage(e) {
displayedImage.src = e.target.src;
displayedImage.alt = e.target.alt;
}
// Solution: Wire up the Darken/Lighten button
// Add a click event listener on the button
btn.addEventListener("click", () => {
// If the button has a "dark" class set,
// change text to "Lighten" and make the overlay darker
if (btn.classList.contains("dark")) {
btn.textContent = "Lighten";
overlay.style.backgroundColor = "rgb(0 0 0 / 0.5)";
} else {
// Else, change text to "Darken" and make
// the overlay lighter
btn.textContent = "Darken";
overlay.style.backgroundColor = "rgb(0 0 0 / 0)";
}
// Toggle the class ready for the next button press
btn.classList.toggle("dark");
});