반응: 사용자 지정 커서(추가 종속성 없음!)

지난번 글과 마찬가지로 이 글도 제 포트폴리오에 있었으면 하는 기능에 초점을 맞춥니다. 사용자 정의 커서.
나는 최근에 이 대접을 많이 보았고 그것이 웹사이트에 약간의 추가 sass를 추가한다고 생각합니다.

이 문서에서는 매우 기본적인 사용자 정의 커서를 만들 것입니다. 이것은 다음 프로젝트를 위해 만들고자 하는 모든 종류의 커서에 대한 기본 설정 역할을 할 수 있습니다.
그럼 바로 들어가 보도록 하겠습니다

P.S.: 다른 의존성은 그냥 반응하지 마세요!!

Github 리포지토리: Click me

라이브 코드SandBox: Click me

설정



다음 명령을 실행하여 기본 반응 앱을 설정합니다.

npx create-react-app custom-cursor
cd custom-cursor
yarn start


최종 파일 구조





useMousePosition():



앞으로 이 저장소에 더 많은 커서를 추가하고 싶기 때문에 마우스의 현재 위치를 가져오기 위한 별도의 후크를 만들었습니다.

이 코드를 src/hooks/useMousePosition.js에 붙여넣으세요.

import { useEffect, useState } from "react";

export default function useMousePosition() {
  const [mousePosition, setMousePosition] = useState({ x: null, y: null });

  useEffect(() => {
    const mouseMoveHandler = (event) => {
      const { clientX, clientY } = event;
      setMousePosition({ x: clientX, y: clientY });
    };
    document.addEventListener("mousemove", mouseMoveHandler);

    return () => {
      document.removeEventListener("mousemove", mouseMoveHandler);
    };
  }, []);

  return mousePosition;
}


간단히 말해서 우리는 mousemove라는 이벤트를 듣고 각 마우스 움직임에 대해 함수mouseMoveHandler를 호출합니다.
그런 다음 함수는 새 좌표로 상태를 업데이트하고 우리의 소중한 작은 후크가 새 좌표를 반환합니다.

사용자 지정 커서



다음은 간단한 점 및 링 커서입니다.

이 코드를 src/components/DotRing/DotRing.js에 붙여넣고 이 코드에 대한 설명을 보려면 아래로 스크롤하십시오.

import "./DotRing.css";
import useMousePosition from "../../hooks/useMousePosition";

const DotRing = () => {
    // 1.
  const { x, y } = useMousePosition();
  return (
    <>
            {/* 2. */}
      <div
        style={{ left: `${x}px`, top: `${y}px` }}
        className="ring"
      ></div>
            {/* 3. */}
      <div
        className="dot"
        style={{ left: `${x}px`, top: `${y}px` }}
      ></div>
    </>
  );
};

export default DotRing;


분석해 보겠습니다.
  • 우리는 {x, y}에서 useMousePosition()를 반환했고 여기에서 그것들을 사용하고 있습니다.
  • 이것은 점 위의 바깥쪽 고리이며 x 및 y 좌표를 이 요소의 왼쪽과 위쪽으로 전달합니다.
  • 이것은 점이며 여기에서도 동일한 작업을 수행하여 left: xtop: y를 통과합니다.

  • DotRing.css




    .ring {
      position: fixed;
      top: 0;
      left: 0;
      width: 22px;
      height: 22px;
      border: 2px solid rgba(31, 30, 30, 0.808);
      border-radius: 100%;
      transform: translate(-50%, -50%);
      -webkit-transition-duration: 100ms;
      transition-duration: 100ms;
      -webkit-transition-timing-function: ease-out;
      transition-timing-function: ease-out;
      will-change: width, height, transform, border;
      z-index: 999;
      pointer-events: none;
    }
    
    .dot {
      position: fixed;
      top: 50%;
      left: 50%;
      width: 8px;
      height: 8px;
      background-color: black;
      border-radius: 100%;
      transform: translate(-50%, -50%);
      z-index: 999;
      pointer-events: none;
    }
    


    여기서 주목해야 할 것은 전환 속성입니다. 우리는 링의 움직임을 100ms 지연시킵니다. 그건 그렇고 이것은 모두 개인 취향입니다.
    will-change 속성:

    The will-change CSS property hints to browsers how an element is expected to change. Browsers may set up optimizations before an element is actually changed. These kinds of optimizations can increase the responsiveness of a page by doing potentially expensive work before they are actually required.



    커서 사용



    App.js




    import "./App.css";
    import DotRing from "./components/DotRing/DotRing";
    
    function App() {
      return (
        <div className="App">
          <DotRing />
          <div className="container"></div>
          <div className="container" style={{ background: "peachpuff" }}></div>
        </div>
      );
    }
    
    export default App;
    


    App.css




    .container {
      height: 100vh;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    
    a {
      text-decoration: none;
      color: black;
    }
    


    index.css



    이것을 index.css에 추가하면 기본 커서가 사라지게 됩니다!

    * {
      cursor: none;
    }
    


    우리는 보기 좋은 커서로 끝났지만 여기에는 한 가지 문제가 있습니다. 커서가 특정 요소에 있을 때 커서가 보이거나 작동하는 방식을 변경할 방법이 없습니다.

    우리는 다음 섹션에서 그렇게 할 것입니다.

    마우스 컨텍스트



    이 코드를 src/context/mouse-context.js에 붙여넣으세요.

    import React, { createContext, useState } from "react";
    
    export const MouseContext = createContext({
      cursorType: "",
      cursorChangeHandler: () => {},
    });
    
    const MouseContextProvider = (props) => {
      const [cursorType, setCursorType] = useState("");
    
      const cursorChangeHandler = (cursorType) => {
        setCursorType(cursorType);
      };
    
      return (
        <MouseContext.Provider
          value={{
            cursorType: cursorType,
            cursorChangeHandler: cursorChangeHandler,
          }}
        >
          {props.children}
        </MouseContext.Provider>
      );
    };
    
    export default MouseContextProvider;
    


    이것은 문자열 cursorType 과 해당 문자열을 변경하는 함수 cursorChangeHandler 를 저장하는 매우 기본적인 컨텍스트입니다.

    BTW, 이것이 처음으로 컨텍스트를 넘어선 경우입니다. 다음은 내 기사에 대한 링크입니다.

    빅 아이디어



    이 컨텍스트를 사용하여 수행하려는 작업은 필수 요소의 cursorTypecursorChangeHandler() 이벤트에서 onMouseEnter()를 호출하여 onMouseLeave()를 변경하는 것입니다.

    나중에 이것을 className으로 커서에 전달하고 커서의 CSS에서 이에 대한 클래스를 정의합니다.

    컨텍스트 사용



    index.js


    cursorType에 코드 붙여넣기

    import React from "react";
    import ReactDOM from "react-dom";
    import "./index.css";
    import App from "./App";
    import reportWebVitals from "./reportWebVitals";
    import MouseContextProvider from "./context/mouse-context";
    
    ReactDOM.render(
      <React.StrictMode>
        <MouseContextProvider>
          <App />
        </MouseContextProvider>
      </React.StrictMode>,
      document.getElementById("root")
    );
    
    // If you want to start measuring performance in your app, pass a function
    // to log results (for example: reportWebVitals(console.log))
    // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
    reportWebVitals();
    


    App.js



    우선권

    import { useContext } from "react";
    import "./App.css";
    import DotRing from "./components/DotRing/DotRing";
    import { MouseContext } from "./context/mouse-context";
    
    function App() {
      const { cursorType, cursorChangeHandler } = useContext(MouseContext);
      return (
        <div className="App">
          <DotRing />
          <div className="container">
            <div
              onMouseEnter={() => cursorChangeHandler("hovered")}
              onMouseLeave={() => cursorChangeHandler("")}
            >
              <h1>Hover over me</h1>
            </div>
          </div>
          <div className="container" style={{ background: "peachpuff" }}></div>
        </div>
      );
    }
    
    export default App;
    


    소품 index.jsonMouseEnter 에 주목하십시오. 이러한 소품은 cursorType을 변경하기 위해 cursorChangeHandler 함수를 호출하는 데 도움이 됩니다.

    이제 DotRing.js 및 DotRing.css 파일을 편집하여 새 변경 사항을 통합합니다.

    DotRing.js


    onMouseLeave를 이 코드로 덮어씁니다.

    import React, { useContext } from "react";
    import "./DotRing.css";
    import useMousePosition from "../../hooks/useMousePosition";
    import { MouseContext } from "../../context/mouse-context";
    
    const DotRing = () => {
        // 1.
      const { cursorType, cursorChangeHandler } = useContext(MouseContext);
    
      const { x, y } = useMousePosition();
      return (
        <>
                {/* 2. */}
          <div
            style={{ left: `${x}px`, top: `${y}px` }}
            className={"ring " + cursorType}
          ></div>
          <div
            className={"dot " + cursorType}
            style={{ left: `${x}px`, top: `${y}px` }}
          ></div>
        </>
      );
    };
    


    그것을 분해하자
  • 여기에서는 컨텍스트에서 항목을 추출합니다
  • .
  • className
  • src/components/DotRing/DotRing.js를 동적으로 추가합니다.

    DotRing.css




    .ring {
      position: fixed;
      top: 0;
      left: 0;
      width: 22px;
      height: 22px;
      border: 2px solid rgba(31, 30, 30, 0.808);
      border-radius: 100%;
      transform: translate(-50%, -50%);
      -webkit-transition-duration: 100ms;
      transition-duration: 100ms;
      -webkit-transition-timing-function: ease-out;
      transition-timing-function: ease-out;
      will-change: width, height, transform, border;
      z-index: 999;
      pointer-events: none;
    }
    
    .dot {
      position: fixed;
      top: 50%;
      left: 50%;
      width: 8px;
      height: 8px;
      background-color: black;
      border-radius: 100%;
      transform: translate(-50%, -50%);
      z-index: 999;
      pointer-events: none;
    }
    
    .ring.hovered {
      width: 50px;
      height: 50px;
      border-width: 3px;
      border-color: lightgray;
    }
    
    .dot.hovered {
      display: none;
    }
    


    시작하기에 충분해야 합니다. 원하는 만큼 멋지게 만들 수 있습니다. 키프레임이나 프레이머 모션을 사용하여 커서에 무한 애니메이션을 추가하거나 목적에 따라 다른 항목cursortype을 추가할 수 있습니다.

    Github 리포지토리: Click me

    라이브 코드SandBox: Click me

    읽어 주셔서 감사합니다



    리뷰를 남겨주세요.

    좋은 웹페이지 즐겨찾기