서론
글을 쓰는 날로부터 약 3개월?전에 어떤 블로그를 봤었다. 그 블로그의 내용은 비밀번호 입력 input에 있는 비밀번호 확인 눈이 마우스를 움직일 때마다 그 방향을 바라보는 기능을 구현해보는 블로그였다. 최근에 시간적으로 여유가 생겨서 구현을 해보려고 블로그를 다시 찾아봤는데 지금은 그 블로그가 서버를 내려서 글을 확인 못하는 상태인것 같다..ㅜ 그래서 직접 생각해보고 구현을 해봤다.
생각해보기
마우스 트래커의 가장 중요한 기능은 당연하게도 마우스 커서를 눈이 따라가는 것이다 해당 기능을 구현하기 위해서 2가지 정도의 방법을 생각했었다.
일단 생각을 해보자 우리가 생각해야할것은 마우스 커서 방향에 따른 눈동자의 위치이다.

내가 생각한 첫번째 방법으로는 마우스 커서 좌표, 눈 중심의 좌표 이렇게 두 점의 좌표가 주어졌을때 직선의 방정식을 구하고 나온 방정식을 눈 중심을 중점으로 하는 원의 방정식에다 대입하여 눈동자의 좌표를 구하는 방법이다.
예시를 들어보자 위에 있는 빨간 테두리의 원의 중점의 좌표는 (0, 0)이고 반지름은 5이다. 그렇다면 원의 방정식을 세울수 있다
x2+y2=52
그리고 마우스 커서의 좌표가 (7, 10)이라면 (0, 0)과 (7, 10) 두 점을 지나는 직선의 방정식을 세울수 있다
y=107x
이렇게 구한 직선의 방정식을 원의 방정식에다 대입을 하여 푼다면 직선과 원의 교점을 알 수 있다
x2+(107x)2=52
x=√1225149,y=50√149149

내가 생각한 두번째 방법으로는 탄젠트의 역함수인 아크 탄젠트를 이용하여 눈의 중점에 대한 절대 각도를 구하고 삼각함수를 이용하여 눈동자의 좌표를 구하는 방법이다.
위의 내용처럼 예시를 들어보자 커서의 좌표가 (7, 10)라면 탄젠트 값을 구할수 있다. (원래는 내부적으로 어떻게 구하는지를 알고 싶었는데 너무 어려워서 탄젠트의 역함수이기 때문에 각을 구할 수 있다 정도로만 이해하고 있다. 언젠가는 내부적으로도 이해하길...)
tan θ=107
atan2(107)=55.0079798
cos(55.0079798)×5=2.8673117
x 좌표 약 2.87
sin(55.0079798)×5=4.0961596
y 좌표 약 4.10

코드로 구현하기
나는 생각한 2가지 방법중에서 2번째 atan2 함수와 삼각함수를 활용하는 방법이 코드로 구현하기 수월하여 2번째 방법으로 구현하였다.
"use client";
import EyeCover from "@/assets/eyeCover";
import { Pupil } from "@/assets/pupil";
import styled from "@emotion/styled";
import { MouseEvent, useRef, useState } from "react";
const 반지름 = 100;
export default function Home() {
const divRef = useRef<HTMLDivElement>(null);
const [coordinate, setCoordinate] = useState<number[]>([0, 0]);
const handleMouseMove = (e: MouseEvent<HTMLDivElement>) => {
if (!divRef.current) return;
const 중점x = divRef.current.getBoundingClientRect().x + 225;
const 중점y = divRef.current.getBoundingClientRect().y + 225;
const [x, y] = [e.clientX, e.clientY];
const 라디안 = Math.atan2(y - 중점y, x - 중점x);
const x좌표 =
Math.cos(라디안) * 반지름 +
divRef.current.getBoundingClientRect().x +
125;
const y좌표 =
Math.sin(라디안) * 반지름 +
divRef.current.getBoundingClientRect().y +
125;
setCoordinate([x좌표, y좌표]);
};
return (
<Container onMouseMove={handleMouseMove}>
<Wrapper ref={divRef}>
<EyeCover />
</Wrapper>
<PupilWrapper style={{ top: coordinate[1], left: coordinate[0] }}>
<Pupil />
</PupilWrapper>
</Container>
);
}
const Container = styled.div`
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
position: relative;
`;
const Wrapper = styled.div`
z-index: 10;
position: relative;
width: 450px;
height: 450px;
`;
const PupilWrapper = styled.div`
z-index: 1;
position: absolute;
width: 200px;
height: 200px;
`;
마무리
마우스 트래커 기능이 어떻게 보면 간단한 기능이라고 생각할 수 있는데 해당 기능을 구현하기 위해서 어느정도의 수학 지식이 있어야 하고
최근 개발을 하면서 수학이 필요하다고 느끼고 있다.
컴퓨터와 프로그래밍이 본래 수학에서 유래한 만큼, 어떤 기능을 구현할 때 일반적인 방법으로 해결할 수도 있지만, 수학적으로 접근하여 해결할 수도 있기 때문에 더 폭넓고 다양한 방식으로 문제를 생각하고 접근할 수 있다고 생각한다.
참고
직선의 방정식 - https://mathbang.net/443#gsc.tab=0
원의 방정식 - https://mathbang.net/454#gsc.tab=0
'JS, TS' 카테고리의 다른 글
aws lambda를 사용해서 디스코드 정기 배포 알림 봇 만들기..! (0) | 2025.04.02 |
---|---|
const a ="객체가 아닌데 왜 되는거야?"; console.log(a.length); (0) | 2025.03.12 |
제발 프로미스나인 팬이라면 Promise 공부하세요🙏 (0) | 2024.08.17 |
js는 단일 쓰레드잖아..!!!!!! (1) | 2024.08.01 |
chunk load error 해결하기..! - 트러블 슈팅 (3) | 2024.07.01 |