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 길이 구하기

DOMRect와 getBoundingClientRect

이번에는 브라우저에게 “이 요소, 화면에서 어디에 있어요?”라고 물어보는 방법을 봅니다.

그 대답이 getBoundingClientRect()입니다. CSS 기반 에디터를 만들 때 이 함수는 꽤 자주 부르게 됩니다. selection outline을 맞추고, hover 대상을 찾고, viewport 안에 보이는지 확인하려면 결국 화면 기준 bounds가 필요합니다.

다만 주의할 점이 있습니다. 이 값은 모델 좌표가 아니라 브라우저가 이미 계산해준 viewport 기준 결과입니다. 친절하지만, 그대로 믿고 저장하면 곤란합니다.

DOMRect는 viewport 기준이다

요소에서 getBoundingClientRect()를 호출하면 left, top, width, height 같은 값이 나옵니다.

const rect = element.getBoundingClientRect();

이때 rect.left와 rect.top은 문서 전체 기준이 아니라 현재 viewport 기준입니다. 화면 왼쪽 위가 원점입니다.

rect = element.getBoundingClientRect()
localX = clientX - rect.left
pageX = clientX + scrollX

포인터의 clientX/clientY도 viewport 기준이므로, 둘을 빼면 요소 내부 local 좌표를 만들 수 있습니다.

localX = clientX - rect.left
localY = clientY - rect.top

아주 자주 쓰는 공식입니다. 너무 자주 나와서 나중에는 손이 먼저 씁니다.

transform된 요소의 rect는 AABB다

회전된 사각형을 생각해봅시다. 원래 width는 100, height는 60이어도 45도 회전하면 화면을 감싸는 직사각형은 더 커집니다.

getBoundingClientRect()는 회전된 모양 자체가 아니라, 그 모양을 화면 축에 맞춰 감싸는 axis-aligned bounding box를 반환합니다.

AABB = min/max(transformed corners)
DOMRect viewport AABB diagramviewport origin (0,0)client pointDOMRectleft/top: viewport 기준width/height: AABBlocal = client - rect
getBoundingClientRect()는 회전된 모양 자체가 아니라 viewport 축에 평행한 AABB를 돌려줍니다.

그래서 회전된 요소의 DOMRect가 원래 width/height보다 커질 수 있습니다. 이걸 모르고 selection bounds를 맞추면 “왜 선택 박스가 커졌지?”라는 질문이 나옵니다. 답은 브라우저가 틀린 게 아니라, 우리가 어떤 bounds를 보고 있는지 구분하지 않은 겁니다.

저장값으로 쓰지는 말자

DOMRect는 빠른 관측값으로 좋습니다. 하지만 에디터의 원본 모델로 저장하기에는 애매합니다. 이미 scroll, layout, transform이 반영된 결과이기 때문입니다.

정확한 모델은 이런 값에서 다시 계산하는 편이 좋습니다.

x, y, width, height, localMatrix, worldMatrix

DOMRect는 화면에 보이는 결과를 확인하거나 빠른 broad phase에 쓰고, 진짜 편집 데이터는 모델에서 관리합니다.

데모에서 볼 것

데모에서는 회전된 요소의 DOMRect가 왜 원래 크기보다 커지는지 확인합니다.

오늘의 핵심은 getBoundingClientRect()가 아주 유용하지만, 어디까지나 viewport 기준 관측값이라는 점입니다. 친절한 조교처럼 써야지, 학적부 원본으로 쓰면 안 됩니다.

Edit this page
최근 수정: 26. 5. 14. PM 5:45
Contributors: easylogic
Prev
Pointer Events와 드래그
Next
hit testing과 bounding box