CSS Graphics Geometry
Guide
Reference
GitHub
Guide
Reference
GitHub
  • Part 0. Math foundations

    • 좌표계와 CSS pixel
    • 점, 벡터, 거리와 기본 용어
    • 각도, 라디안, atan2
  • Part 1. Transform linear algebra

    • translate, scale, rotate
    • CSS matrix(a,b,c,d,e,f)
    • 변환 순서와 transform-origin
    • local, world, screen 좌표계
    • inverse matrix와 포인터 입력
    • 좌표와 transform 디버깅
  • Part 2. Infinite canvas math and architecture

    • viewport와 camera 모델
    • cursor anchored zoom
    • ruler와 tick 계산
    • 주기 함수와 grid step
    • content, overlay, controls layer
    • scene graph와 nested transform
  • Part 3. Editor tool math

    • Pointer Events와 드래그
    • DOMRect와 getBoundingClientRect
    • hit testing과 bounding box
    • selection rectangle과 marquee
    • selection bounds와 handles
    • resize와 rotation handle
    • snapping과 smart guides
    • group, frame, clipping
  • Part 4. CSS graphics properties as math

    • CSS box로 도형 만들기
    • clip-path, radius, shadow
    • 선형보간과 linear-gradient
    • 거리 함수와 radial/conic-gradient
    • stacking context와 합성
    • layout, paint, composite
  • Part 5. Editor state and persistence

    • 레이어 모델과 z-index
    • 이동, 복제, 삭제, 잠금
    • undo/redo command model
    • JSON export/import
  • Part 6. SVG overlay and vector editing

    • SVG viewBox와 좌표계
    • getScreenCTM과 inverse
    • SVG pointer-events와 stroke hit testing
    • cubic bezier path editing
    • mask, clipPath, marker
  • Part 7. Figma to CSS translation

    • Figma node와 CSS DOM 모델
    • Frame constraints와 Auto Layout
    • Fills, strokes, effects를 CSS로
    • Vector와 text 변환
    • gradient 밖의 CSS 수학
    • Figma gradient를 CSS gradient로 변환하기
    • 수학이 필요한 Figma to CSS 속성들
    • Figma VectorNetwork 정리
  • Appendix A. Canvas renderer transition

    • Canvas로 넘어가는 기준
  • Appendix B. Motion and timing

    • 모션 수학과 timing 함수
    • Keyframe timeline 엔진
    • Motion path 수학
    • Bezier curve 길이 구하기

ruler와 tick 계산

ruler는 화면 위에 얹힌 작은 눈금자처럼 보입니다. 그런데 사실은 world 좌표를 screen 위에 번역해 보여주는 장치입니다.

여기서 재미있는 점은 위치와 의미가 서로 다른 좌표계를 쓴다는 겁니다. tick의 위치는 screen pixel이고, label의 값은 world 좌표입니다. 겉보기에는 조용하지만 속은 꽤 바쁩니다.

tick은 world에서 만들고 screen에 그린다

현재 보이는 world range를 먼저 구합니다. 그리고 그 범위 안에서 일정 간격으로 tick을 만듭니다.

이 수식은 행렬을 안 쓰는 대충 버전이 아닙니다. 2D camera 행렬을 ruler의 x축 한 줄에만 풀어 쓴 형태입니다.

screen = Scale(zoom) * Translate(-camera) * world

이걸 x축 tick 하나에만 적용하면 이렇게 됩니다.

tickScreen = (tickWorld - camera) * zoom

여기서 중요한 질문은 “camera가 무엇을 뜻하냐”입니다. 에디터 본문에서는 보통 camera를 viewport 중심으로 둡니다. 그런데 ruler overlay에서는 화면 왼쪽 끝을 기준으로 잡으면 계산이 더 단순할 때가 많습니다.

cameraLeft = viewport 왼쪽 끝에 해당하는 world x
tickScreen = (tickWorld - cameraLeft) * zoom

예를 들어 cameraLeft = -75, zoom = 1.4, tickWorld = 0이면:

tickScreen = (0 - (-75)) * 1.4
           = 105px

이 말은 world의 x = 0 눈금이 ruler overlay의 왼쪽에서 105px 떨어진 곳에 찍힌다는 뜻입니다.

같은 장면을 viewport 중심 camera 모델로 쓰면 기준 offset이 하나 더 붙습니다.

cameraCenter = cameraLeft + viewportWidth / (2 * zoom)
domX = viewportCenterX + (tickWorld - cameraCenter) * zoom

둘은 서로 다른 수식이 아니라 기준점을 다르게 잡은 같은 변환입니다. 왼쪽 기준 ruler는 cameraLeft를 쓰고, 중앙 기준 infinite canvas는 cameraCenter와 viewportCenterX를 같이 씁니다. 이걸 구분하면 머리가 덜 어지럽습니다. 그래픽 수학에서 머리 덜 어지러운 건 꽤 큰 복지입니다.

이때 label은 tickWorld 값을 보여주고, 실제 CSS 위치는 tickScreen 또는 domX를 씁니다.

보기 좋은 간격 고르기

zoom이 바뀌면 같은 world step도 화면에서 너무 좁거나 넓어질 수 있습니다. 그래서 목표 screen 간격을 정한 뒤, 그에 맞는 world step을 고릅니다.

targetWorldStep = targetScreenPx / zoom
niceStep = 1, 2, 5 * 10^n 중 가까운 값

1, 2, 5 계열은 ruler에서 자주 씁니다. 사람 눈에 익숙하고 label이 지저분해지지 않습니다. 37.418 같은 눈금이 잔뜩 나오면 교육용 데모가 아니라 계산기 벌칙처럼 보입니다.

overlay에 둔다

ruler는 content transform에 직접 포함하지 않는 편이 좋습니다. 화면 가장자리에 고정된 overlay로 두고, 내부 tick만 camera/zoom에 맞춰 계산합니다.

major/minor tick을 나누면 zoom 변화 중에도 더 안정적으로 보입니다. guide, snap distance label도 같은 tick 생성 정책을 공유하면 전체 도구의 감각이 통일됩니다.

데모에서 볼 것

데모에서는 zoom을 바꾸며 ruler step이 1/2/5 계열로 바뀌는 순간을 확인합니다.

오늘의 핵심은 ruler가 단순한 장식이 아니라 좌표 변환 UI라는 점입니다. 위치는 screen, 의미는 world. 이 둘을 같이 들고 가야 합니다.

Edit this page
최근 수정: 26. 5. 14. PM 5:45
Contributors: easylogic
Prev
cursor anchored zoom
Next
주기 함수와 grid step