next js와 tailwind를 사용해 제작한 mac os 컨셉의 포트폴리오 입니다. 각 프로젝트에 관한 내용을 browser 처럼 열어서 확인 가능하며, 마우스를 통해 움직이거나 크기를 조정하는 동작이 가능합니다.
Vercel을 통한 배포 ▶︎
바로 가기
state를 통해 위치와 크기값이 동적으로 정해지는 전체적인 뼈대가 될 div와 mouse event를 통해 left와 top 값을 변화시킬 div를 만들어 구현했습니다. 기능 구현은 bepyan님 블로그를 참고하였습니다.
function Browser() {
const [browserConfig, setBrowserConfig] = useState({
x: 0,
y: 0,
w: 0,
h: 0,
});
return (
<div className="browser-container">
<div
className="browser-mover browser-topbar"
{...dragMouseDown((intercalX, intervalY) => {
setBrowserConfig({
x: x + intervalX,
t: y + intervalY,
w,
h,
});
})}
></div>
</div>
);
}onMouseDown 객체를 반환하는 utill 함수를 통해 mouseMove의 시작 위치과 실시간 위치를 빼어 움직인 거리를 인자로 받는 콜백함수에 전달하여 원하는 동작이 가능하도록 구현했습니다.
function dragMouseDown(
onDrag: (intervalX: number, intervalY: number) => void,
stopPropagation?: boolean
) {
if (stopPropagation) e.stopPropagation();
const mouseMoveHandler = (mouseE: MouseEvent) => {
const intervalX = mouseE.screenX - e.screenX;
const intervalY = mouseE.screenY - e.screenY;
onDrag(intervalX, intervalY);
};
const mouseUpHandler = () => {
document.removeEventListener("mousemove", mouseMoveHandler);
};
document.addEventListener("mousemove", mouseMoveHandler);
document.addEventListener("mouseup", mouseUpHandler, { once: true });
}resize의 경우 x,y 값이 변화하는 만큼 w,h을 증가시키거나 감소시켜 반대편 테두리의 위치를 고정했습니다.
function Browser() {
const [browserConfig, setBrowserConfig] = useState({
x: 0,
y: 0,
w: 0,
h: 0,
});
const inrange = (n: number, min: number, max: number) => {
if (n < min) return min;
if (n > max) return max;
return n;
};
return (
<div className="browser-container">
<div
className="browser-resizer n"
{...dragMouseDown((intercalX, intervalY) => {
setBrowserConfig({
x,
y: inrange(y + interval.y, 0, y + h - MIN_H),
w,
h: inrange(h - interval.y, MIN_H, y + h),
});
})}
></div> {/* x8 (n,s,w,e,nw,ne,sw,se)*/}
</div>
);
}