ReactJS 및 Styled-Components로 슬라이드쇼 갤러리를 만드는 방법

25609 단어 reactjavascript
슬라이드쇼 갤러리는 웹에서 볼 수 있는 시각적 표시 모드의 일부입니다. 한 번에 하나의 사진을 과감하게 표시하고 다른 사진은 옆에 남겨 두어 사용자가 이미지 사이를 이동할 수 있도록 도와줍니다.

이 블로그 게시물은 전체 뷰포트 슬라이드쇼 갤러리를 구축하는 방법을 보여줍니다.

전제 조건


  • JavaScript, React 및 styled-components에 대한 기본 지식

  • The complete code is in this repo.



    슬라이드쇼 갤러리 레이아웃



    슬라이드쇼의 구성은 어떻게 됩니까? 다음 와이어 프레임으로 우리를 덮었습니다.



    슬라이드 래퍼



    와이어프레임에서 컨테이너가 모든 요소를 ​​래핑하는 것을 볼 수 있습니다. 먼저 SlideWrapper 스타일 구성 요소를 생성해 보겠습니다.

    // src/slideshow-gallery/index.js
    import styled from 'styled-components';
    
    const View = () => <Slideshow />;
    
    const Slideshow = () => {
      return <SlideWrapper></SlideWrapper>;
    };
    
    const SlideWrapper = styled.div`
      position: relative;
      width: 100vw;
      height: 100vh;
    `;
    
    export default View;
    

    SlideWrapper는 전체 뷰포트의 너비와 높이를 차지합니다. 우리는 전체 뷰포트 슬라이드쇼를 원했습니다. 맞죠? 그리고 아이들은 이 래퍼를 기준으로 위치를 지정하므로 position: relative; .

    이미지 상자



    선택한 각 이미지는 이미지 비율(너비/높이)을 유지하는 상자에 있습니다. <img> 라는 ImageBox 태그 주위에 래퍼를 만들어 보겠습니다. 이 래퍼는 이미지를 제약 조건에 넣습니다. 즉, 이미지는 래퍼의 경계 내에 있어야 합니다. 그렇게 하면 이미지 크기와 방향에 관계없이 슬라이드쇼가 안정적으로 유지됩니다.



    다음에서는 ImageBox 구성 요소를 정의하고 사용합니다.

    // src/slideshow-gallery/index.js
    // ...
    const ImageBox = styled.div`
      position: relative;
      background-color: #343434;
      width: 100%;
      height: 85%;
    
      img {
        position: absolute;
        margin: auto;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
        max-width: 100%;
        max-height: 100%;
      }
    `;
    
    const Slideshow = () => {
      return (
        <SlideWrapper>
          <ImageBox>
            <img alt="" src="/pathToAnImage" />
          </ImageBox>
        </SlideWrapper>
      );
    };
    //...
    


    다음은 이미지 방향과 크기가 다른 결과입니다.



    우리ImageBox는 이미지 사이를 전환하는 데 도움이 되는 왼쪽 및 오른쪽 버튼이 필요합니다. 이를 수행하기 위해 NavButton 스타일 구성 요소를 만들어 보겠습니다.

    // src/slideshow-gallery/index.js
    import styled, { css } from 'styled-components';
    
    import rurikoTempleImage from './assets/ruriko-in-temple.jpeg';
    import { ReactComponent as ChevronLeft } from './assets/chevron-left.svg';
    import { ReactComponent as ChevronRight } from './assets/chevron-right.svg';
    
    // ...
    
    const Slideshow = () => {
      return (
        // ...
        <ImageBox>
          <img alt="" src={rurikoTempleImage} />
          <NavButton position="left">
            <ChevronLeft />
          </NavButton>
          <NavButton position="right">
            <ChevronRight />
          </NavButton>
        </ImageBox>
        // ...
      );
    };
    
    const NavButton = styled.button`
      cursor: pointer;
      position: absolute;
      top: 45%;
      padding: 5px;
      border-radius: 3px;
      border: none;
      background: rgba(255, 255, 255, 0.7);
    
      ${({ position }) =>
        position === 'left' &&
        css`
          left: 10px;
        `}
    
      ${({ position }) =>
        position === 'right' &&
        css`
          right: 10px;
        `}
    `;
    
    // ...
    

    NavButtonImageBox ( top: 45%; )에서 수직으로 중앙에 있습니다. 위치 소품에 따라 NavButton가 왼쪽 또는 오른쪽에 배치됩니다.



    하단에 캡션이 있는 것도 좋을 것입니다.

    // src/slideshow-gallery/index.js
    const Slideshow = () => {
      return (
        <SlideWrapper>
          <ImageBox>
            // ...
            <ImageCaption>Ruriko Temple</ImageCaption>
          </ImageBox>
        </SlideWrapper>
      );
    };
    
    // ...
    
    const ImageCaption = styled.span`
      width: 100%;
      text-align: center;
      font-weight: bold;
      position: absolute;
      bottom: 0;
      padding: 8px;
      background: rgba(255, 255, 255, 0.7);
    `;
    
    // ...
    


    그리고 우리는 다음을 얻습니다.



    슬라이드쇼 항목을 소품으로 가져오기



    슬라이드쇼는 외부에서 일련의 이미지를 가져와야 합니다. src/slideshow-gallery/data.js 파일은 우리가 사용할 수 있는 그림 배열을 내보냅니다. 각 항목은 이미지 소스와 이미지 캡션에 대한 액세스를 제공합니다.

    // src/slideshow-gallery/data.js
    import rurikoTemple from './assets/ruriko-in-temple.jpeg';
    import itsukushimaShrine from './assets/itsukushima-shrine.jpeg';
    // ...
    const slideItems = [
      {
        image: nemichiJinja,
        caption: 'Nemichi-Jinja, Seki',
      },
      {
        image: itsukushimaShrine,
        caption: 'Itsukushima Shrine',
      },
      // ...
    ];
    
    export default slideItems;
    


    이 배열을 가져와서 Slideshow 구성 요소로 전달해 보겠습니다.

    // src/slideshow-gallery/index.js
    // ...
    import data from './data';
    
    const View = () => <Slideshow items={data} />;
    // ...
    

    Slideshow 구성 요소는 선택한 이미지에 따라 다르게 렌더링되므로 상태를 사용해야 합니다. 이 상태는 현재 활성 항목의 색인 외에 모든 슬라이드 항목을 보유합니다.

    // src/slideshow-gallery/index.js
    import { useState } from 'react';
    // ...
    const Slideshow = (props) => {
      const [{ items, activeIndex }, setState] = useState({
        items: props.items,
        activeIndex: 0, // begin with the first item
      });
    
      return (
        <SlideWrapper>
          <ImageBox>
            <img alt={items[activeIndex].caption} src={items[activeIndex].image} />
            <NavButton position="left">
              <ChevronLeft />
            </NavButton>
            <NavButton position="right">
              <ChevronRight />
            </NavButton>
            <ImageCaption>{items[activeIndex].caption}</ImageCaption>
          </ImageBox>
        </SlideWrapper>
      );
    };
    // ...
    


    이미지 간 탐색



    상태가 적절하면 각각에 클릭 핸들러 함수NavButton를 추가하여 이미지를 변경할 수 있습니다.

    // src/slideshow-gallery/index.js
    // ...
    const Slideshow = (props) => {
      // ...
      const moveTo = (newIndex) => () => {
    
        if (newIndex === -1) {
          // jump from the first image to the last
          setState((s) => ({ ...s, activeIndex: items.length - 1 }));
          return;
        }
        if (newIndex === items.length) {
          // jump from the last image to the first
          setState((s) => ({ ...s, activeIndex: 0 }));
          return;
        }
    
        setState((s) => ({ ...s, activeIndex: newIndex }));
      };
    
      return (
        <SlideWraper>
            // ...
            <NavButton position="left" onClick={moveTo(activeIndex - 1)}>
            // ...
            <NavButton position="right" onClick={moveTo(activeIndex + 1)}>
            // ...
        </SlideWraper>
      );
    };
    // ...
    


    썸네일 이미지


    ImageBox 다음에 모든 이미지에 대한 축소판 목록이 필요합니다. 해당 목록은 100% 불투명도의 활성 이미지 축소판을 표시합니다. 비활성 항목은 40% 투명합니다.

    // src/slideshow-gallery/index.js
    // ...
    const Slideshow = (props) => {
      // ...
      return (
        <SlideWraper>
          // ...
          </ImageBox>
          <ThumbnailList>
            {items.map((item, index) => (
              <Thumbnail active={activeIndex === index} src={item.image} />
            ))}
          </ThumbnailList>
        </SlideWraper>
      );
    };
    
    const ThumbnailList = styled.div`
      display: flex;
      align-items: stretch;
      width: 100%;
      height: 15%;
    `;
    const Thumbnail = styled.div`
      cursor: pointer;
      opacity: ${({ active }) => (active ? 1 : 0.6)};
      background-image: url(${({ src }) => src});
      background-size: cover;
      background-position: center;
      flex-grow: 1;
    
      :hover {
        opacity: 1;
      }
    `;
    // ...
    


    마지막으로 축소판을 클릭하여 이미지로 직접 이동하려고 합니다. 이를 위해 moveTo 함수를 재사용합니다.

    // src/slideshow-gallery/index.js
    // ...
    {
      items.map((item, index) => (
        <Thumbnail
          onClick={moveTo(index)}
          // ...
        />
      ));
    }
    // ...
    


    이제 슬라이드쇼 갤러리가 준비되었습니다! 최종 결과를 살펴보십시오.



    결론



    와이어프레임에서 슬라이드쇼의 뚜렷한 부분을 분해했습니다. 최종 UI까지 구축한 초석이었습니다.

    당신은 끝까지 그것을 만들기 위해 등을 두드릴 수 있습니다.

    읽어 주셔서 감사합니다!

    좋은 웹페이지 즐겨찾기