1. Overview

Challenge & starter files: Advent of JS

Full codes: nilstarbb/advent-of-js/9-image-carousel

Live Demo: 09 - Image Carousel || Advent of JavaScript

Preview:

image-carousel.gif

2. Details

Users should be able to:

  • toggle left and right through the image thumbnails
  • click an image to select it manually

3. Coding

Setup React template

index.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    ...
    <link rel="stylesheet" href="./styles.css" />

    <script src="https://unpkg.com/react@17/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
  </head>

  <body>
    <div class="wrapper menu" id="wrapper"></div>
    <script type="text/babel" src="./script.js"></script>
  </body>
</html>

script.js:

const { useState, useEffect } = React;

const App = () => {
  return (
    <>
			...
    </>
  );
};

ReactDOM.render(<App />, document.getElementById("wrapper"));

Carousel 的逻辑如下:

  1. 数组 content 储存图片信息,selected 记录当前主图序号。
  2. 初始化显示第一张图片 content[0] 为主图。
  3. 点击下方缩略图后,用该图片替换主图,更新 selected。
  4. 点击左/右箭头,替换主图为前/后一张图片,selected--/selected++
  5. 限定 selected 的取值范围:selected >= 0 && selected < content.length
const App = () => {
  const [selected, setSelected] = useState(0);

  const changeSelected = (key) => {
    if (key >= 0 && key < content.length) {
      setSelected(key);
    }
  };

  return (
    <>
      <div className="feature">
        <img
          src={"./images/" + content[selected].image}
          alt={content[selected].caption}
        />
        <div className="caption">{content[selected].caption}</div>
      </div>

      <div className="thumbnails">
        <ul>
          {content.map((img, index) => (
            <li
              key={index}
              className={selected == index ? "selected" : ""}
              onClick={() => changeSelected(index)}
            >
              <a href="#">
                <img src={"./images/" + img.image} alt={img.caption} />
              </a>
            </li>
          ))}
        </ul>
      </div>

      <a href="#" className="left" onClick={() => changeSelected(selected - 1)}>
        <img src="./images/chevron.svg" alt="" />
      </a>
      <a
        href="#"
        className="right"
        onClick={() => changeSelected(selected + 1)}
      >
        <img src="./images/chevron.svg" alt="" />
      </a>
    </>
  );
};