1. 어떤 사이트?
CSS로 Figma 같은 그래픽 툴을 만들고 싶은 사람을 위한 선형대수·기하학 강의를 표방하는 사이트이다. (슬로건은 "Math first")
평소 보던 CSS 문서가 이 속성으로 이런 효과를 낼 수 있어요 식이라면, 이쪽은 회전된 박스 위에 마우스가 들어왔는지 어떻게 판단할 건가 같은 에디터 문제에서 출발해 좌표·벡터·행렬로 푸는 흐름이다.
2. 인사이트 1 - transport layr 잘 구현하기
에디터에서 자주 등장하는 동작들은 사실 거의 다 같은 식 위에 얹혀 있다.
- 마우스가 어떤 객체 위에 있는지 판단 (hit test)
- 마우스 드래그로 객체 옮기기
- 휠로 줌 인/아웃 (특히 커서 위치를 기준으로 줌)
- marquee selection, 스냅핑, 가이드
이 모든 게 결국 화면 좌표 ↔ 캔버스(월드) 좌표 변환이라는 한 겹의 변환에 기댄다. 카메라가 (x, y, zoom)이라고 할 때, 변환은 다음 두 함수가 전부다.
ts
type Camera = { x: number; y: number; zoom: number };
function screenToCanvas(sx: number, sy: number, cam: Camera) {
return { x: (sx - cam.x) / cam.zoom, y: (sy - cam.y) / cam.zoom };
}
function canvasToScreen(cx: number, cy: number, cam: Camera) {
return { x: cx * cam.zoom + cam.x, y: cy * cam.zoom + cam.y };
}이걸 잘 깔아두면 줌·드래그·스냅 같은 동작들이 별개 기능이 아니라 같은 좌표계 위의 작은 식으로 바뀔 수 있다.
3. 인사이트 2 - Cursor-anchored zoom
Figma에서 마우스 휠로 줌하면 커서가 가리키던 지점이 화면에서 움직이지 않는다. 아래 변환 식만 있으면 자연스럽게 유도된다.
조건은 한 줄이다.
text
줌 전 커서 아래 캔버스 좌표 === 줌 후 커서 아래 캔버스 좌표식으로 풀면:
ts
function zoomAt(sx: number, sy: number, factor: number, cam: Camera) {
// 1) 줌 전, 커서가 가리키는 캔버스 좌표를 기억
const before = screenToCanvas(sx, sy, cam);
// 2) 줌 적용
cam.zoom *= factor;
// 3) 같은 캔버스 좌표가 같은 화면 좌표를 가리키도록 카메라 재배치
// canvasToScreen(before, cam) === (sx, sy) 가 되어야 함
cam.x = sx - before.x * cam.zoom;
cam.y = sy - before.y * cam.zoom;
}에디터의 인터랙션은 CSS 트릭의 모음이 아니라, 잘 정의된 좌표 변환 한 겹 위에 얹힌 작은 식들의 모음이다.