useImageZoom React 후크를 작성해 봅시다.

이 기사에서는 이미지 "확대/축소"기능을 처리하는 기본 React 후크를 제시할 것입니다.

우리가 구축할 것





목표는 세 개의 핸들러를 제공하는 useImageZoom 후크를 만드는 것입니다.
  • 확대
  • 축소
  • 줌 재설정

  • 이를 염두에 두고 후크가 노출할 수 있는 API를 이미 계획할 수 있습니다.

    const [zoomStyles, handlers] = useImageZoom();
    


    일반적인 규칙에 따라 두 요소 배열을 반환합니다.

    첫 번째 요소는 이미지에 적용되는 스타일 객체이고 두 번째 요소는 앞서 언급한 핸들러를 포함합니다.

    후크 구현




    // App.jsx
    
    import React from "react":
    
    function useImageZoom(maxZoomLevel = 5) {
      const minZoomLevel = 1;
    
      const [zoomLevel, setZoomLevel] = React.useState(minZoomLevel);
    
      function zoomIn() {
        setZoomLevel(zoomLevel =>
          zoomLevel < maxZoomLevel ? zoomLevel + 1 : zoomLevel
        );
      }
    
      function zoomOut() {
        setZoomLevel(zoomLevel =>
          zoomLevel > minZoomLevel ? zoomLevel - 1 : minZoomLevel
        );
      }
    
      function resetZoom() {
        setZoomLevel(minZoomLevel);
      }
    
      const zoomStyles = {
        transform: `scale(${zoomLevel})`,
      };
    
      const handlers = {
        zoomIn,
        zoomOut,
        resetZoom
      }
    
      return [zoomStyles, handlers];
    }
    


    구현에 대한 몇 마디.

    CSS에서 이미지 크기 조정을 처리하려면 transform 속성을 사용하고 scale(x)를 값으로 전달해야 합니다. 기본적으로 x는 1과 같으므로 minZoomLevel 변수에 1을 할당합니다.
    maxZoomLevel는 후크가 허용하는 유일한 매개변수이며 기본값은 5입니다.
    zoomInzoomOut 함수에서 확대/축소 수준을 각각 증가 및 감소하지만 maxZoomLevelminZoomLevel 경계에 유지합니다.
    resetZoom는 단순히 minZoomLevel 값을 설정합니다.

    용법




    // App.jsx
    
    import React from "react";
    import ReactDOM from "react-dom";
    
    import "./styles.css";
    
    // function useImageZoom(maxZoomLevel = 5) {
    //   ...
    // }
    
    function App() {
      const [zoomStyles, handlers] = useImageZoom();
    
      return (
        <div className="app">
          <div className="buttons">
            <button onClick={handlers.zoomIn}>Zoom in</button>
            <button onClick={handlers.zoomOut}>Zoom out</button>
          </div>
          <div className="preview">
            <img
              style={{ ...zoomStyles }}
              onClick={handlers.resetZoom}
              src="https://placeimg.com/150/150/arch"
              alt="preview box"
            />
          </div>
        </div>
      );
    }
    
    const rootElement = document.getElementById("root");
    ReactDOM.render(<App />, rootElement);
    
    



    /* styles.css */
    
    .app {
      display: flex;
      flex-direction: column;
      align-items: center;
      font-family: sans-serif;
      text-align: center;
    }
    
    .buttons {
      margin-top: 50px;
    }
    
    .preview {
      display: flex;
      align-items: center;
      justify-content: center;
      height: 300px;
      width: 300px;
      margin-top: 50px;
      background: #eee;
      overflow: auto;
      position: relative;
    }
    
    


    실제로 그것을 보자.



    아시다시피 문제가 있습니다. 확대하면 이미지의 양쪽이 점점 잘립니다.

    개량



    문제는 transform-origin 의 초기 값이 주어진 이미지의 중심에 해당하는 "50% 50%" 와 같다는 것입니다. 이 속성이 무엇을 하는지 이해하려면 this page 을 참조하십시오.

    솔루션을 적용하려면 zoomStyles 개체를 다음으로 변경합니다.

    const zoomStyles = {
      transform: `scale(${zoomLevel})`,
      transformOrigin: "top left"
    };
    


    무슨 일이 일어나는지 봅시다.



    자, 이미지가 잘리지는 않지만 또 다른 문제가 있습니다. 미리보기 상자의 왼쪽과 상단에 빈 공간이 있다는 것을 눈치채셨나요? 이미지가 사용 가능한 전체 공간을 채우도록 강제할 수 있지만 여전히 초기 중앙 위치를 유지합니다.

    미리 보기 상자의 왼쪽 상단 모서리에 이미지를 완전히 배치하여 수행할 수 있지만 1보다 큰 확대/축소 수준이 적용된 경우에만 가능합니다.
    zoomStyles 개체를 다음으로 변경합니다.

    const zoomStyles = {
      transform: `scale(${zoomLevel})`,
      transformOrigin: "top left",
      position: zoomLevel > 1 ? "absolute" : undefined,
      top: zoomLevel > 1 ? 0 : undefined,
      left: zoomLevel > 1 ? 0 : undefined
    };
    


    Voilà, 작동합니다!



    최종 버전은 codesandbox에서 사용할 수 있습니다.

    다음 기사에서는 useImageZoom hook을 더 유연하고 사용하기 쉽게 만들 것입니다. 계속 지켜봐!

    좋은 웹페이지 즐겨찾기