content, overlay, controls layer
이번에는 레이어 구조입니다.
CSS 기반 infinite canvas를 만들 때 모든 것을 한 div 안에 넣고 시작하면 처음에는 편합니다. 그런데 selection box, guide, ruler, toolbar가 들어오는 순간 서로 zoom을 받을지 말지 싸우기 시작합니다.
그래서 보통 content, overlay, controls로 나눕니다. 레이어를 나누면 누가 camera transform을 받는지 명확해집니다.
content layer
content layer에는 실제 오브젝트 DOM이 들어갑니다. 이 레이어는 pan/zoom의 영향을 받습니다.
contentScreen = V * objectWorld
V는 viewport matrix입니다. 오브젝트는 world에 있고, content layer가 그것을 screen으로 보내줍니다.
overlay layer
overlay에는 selection box, resize handle, guide 같은 편집 UI를 둡니다. 이 UI들은 content 위에 보이지만 content 자체는 아닙니다.
overlayScreen = project(worldBounds, V)
handle 크기는 zoom해도 화면에서 일정해야 합니다. content 안에 넣고 같이 scale하면 zoom할수록 handle이 너무 커지거나 작아집니다. 사용자는 handle을 잡고 싶은데 handle이 점처럼 작아지면 꽤 서운합니다.
controls layer
toolbar, context menu, property panel은 zoom 영향을 받으면 안 됩니다.
controlsScreen = fixed viewport coordinates
이 레이어는 일반 앱 UI처럼 viewport에 고정됩니다. canvas camera가 움직여도 toolbar가 같이 날아가면 안 됩니다.
pointer-events도 쉬워진다
레이어를 나누면 입력 정책도 단순해집니다. overlay 장식은 pointer-events: none, handle처럼 잡아야 하는 UI는 pointer-events: auto로 둘 수 있습니다.
데모에서 볼 것
데모에서는 overlay handle 크기가 zoom해도 변하지 않는 이유를 layer 구조로 설명합니다.
오늘의 핵심은 “무엇이 world에 속하고, 무엇이 화면 UI에 속하는가”를 레이어로 나누는 것입니다. 이 구분이 있어야 infinite canvas가 덜 헷갈립니다.