반응: 사용자 지정 커서(추가 종속성 없음!)
나는 최근에 이 대접을 많이 보았고 그것이 웹사이트에 약간의 추가 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;
분석해 보겠습니다.
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;
분석해 보겠습니다.
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;
}
다음은 간단한 점 및 링 커서입니다.
이 코드를
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()
를 반환했고 여기에서 그것들을 사용하고 있습니다. left: x
및 top: 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, 이것이 처음으로 컨텍스트를 넘어선 경우입니다. 다음은 내 기사에 대한 링크입니다.
빅 아이디어
이 컨텍스트를 사용하여 수행하려는 작업은 필수 요소의 cursorType
및 cursorChangeHandler()
이벤트에서 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.js
및 onMouseEnter
에 주목하십시오. 이러한 소품은 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>
</>
);
};
그것을 분해하자
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;
.container {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
a {
text-decoration: none;
color: black;
}
* {
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, 이것이 처음으로 컨텍스트를 넘어선 경우입니다. 다음은 내 기사에 대한 링크입니다.
빅 아이디어
이 컨텍스트를 사용하여 수행하려는 작업은 필수 요소의
cursorType
및 cursorChangeHandler()
이벤트에서 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.js
및 onMouseEnter
에 주목하십시오. 이러한 소품은 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>
</>
);
};
그것을 분해하자
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();
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;
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>
</>
);
};
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
읽어 주셔서 감사합니다
리뷰를 남겨주세요.
Reference
이 문제에 관하여(반응: 사용자 지정 커서(추가 종속성 없음!)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/holdmypotion/react-custom-cursor-no-extra-dependencies-25ki텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)