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

변환 순서와 transform-origin

이번에는 transform에서 사람을 제일 많이 헷갈리게 만드는 두 가지를 봅니다.

순서와 기준점입니다.

같은 translate, rotate, scale을 써도 순서가 바뀌면 결과가 달라집니다. 그리고 같은 회전을 해도 어디를 기준으로 돌리느냐에 따라 화면 위치가 달라집니다. transform은 숫자만 맞다고 끝나는 세계가 아닙니다. 순서와 origin까지 같이 봐야 합니다.

transform origin diagramtop-left originpivot이 corner라서 박스가 크게 휘돈다center originpivot이 center라서 제자리에서 돈다
같은 rotate라도 origin이 top-left인지 center인지에 따라 최종 위치가 달라집니다.

행렬 곱은 순서를 탄다

숫자 곱셈은 보통 순서를 바꿔도 같습니다.

2 * 3 = 3 * 2

하지만 행렬 곱은 그렇지 않습니다.

A * B != B * A

그래서 translate 후 rotate와 rotate 후 translate는 다른 결과를 만듭니다. 하나는 이동한 다음 돌고, 다른 하나는 돌아간 좌표계에서 이동합니다. 말장난 같지만 화면에서는 확실히 다르게 보입니다.

CSS transform 목록도 최종 matrix를 만들 때 순서가 결과에 영향을 줍니다. 편집기에서는 이 순서를 테스트로 고정해두는 것이 좋습니다. “아마 이 순서겠지”는 나중에 꼭 발목을 잡습니다.

transform-origin은 몰래 들어가는 변환이다

CSS의 transform-origin은 회전과 스케일의 기준점을 정합니다. 예를 들어 center 기준 회전은 그냥 R 하나가 아니라, origin으로 옮겼다가 회전하고 다시 되돌리는 과정입니다.

M = T(origin) * R * S * T(-origin)

이렇게 보면 origin이 왜 중요한지 보입니다. 기준점이 바뀌면 같은 각도, 같은 scale이어도 최종 위치가 달라집니다.

Figma와 CSS는 기본 기준점이 다르다

여기서 Figma export를 만들 때 자주 나오는 차이가 있습니다.

Figma rotation 기준점 = object의 local top-left
CSS transform 기본 기준점 = element의 center

Figma plugin API의 rotation은 node의 top-left 기준으로 해석됩니다. 반면 CSS는 아무 설정을 하지 않으면 transform-origin: 50% 50%입니다. 그래서 Figma의 relativeTransform을 CSS matrix(...)로 그대로 옮길 때는 보통 origin을 명시합니다.

.figma-node {
  position: absolute;
  width: 120px;
  height: 80px;
  transform-origin: 0 0;
  transform: matrix(a, b, c, d, e, f);
}

transform-origin: 0 0은 “이 matrix는 local top-left를 기준으로 계산된 값입니다”라고 브라우저에게 알려주는 안전핀입니다. 이걸 빼먹으면 matrix 숫자는 맞는데 화면 위치가 살짝 틀어집니다. 숫자가 맞는데 틀리는 버그, 아주 얄밉죠.

반대로 center 기준 회전을 직접 만들고 싶다면 origin 속성에 기대지 말고 translation을 다시 계산할 수 있습니다.

pivotLocal = (width / 2, height / 2)
pivotParent = oldMatrix * pivotLocal

newTranslation =
  pivotParent - newLinearPart * pivotLocal

임의의 pivot도 똑같습니다.

pivotLocal = (px, py)
pivotParent = oldMatrix * pivotLocal
newE = pivotParent.x - (a * px + c * py)
newF = pivotParent.y - (b * px + d * py)

즉 transform-origin은 “각도를 바꾸는 속성”이 아니라, pivot이 움직이지 않도록 translation을 보정하는 문제로 볼 수 있습니다.

에디터는 origin 정책을 정해야 한다

CSS의 기본 transform-origin은 center입니다. 하지만 에디터 내부 수학 모델은 top-left 기준으로 계산하는 경우가 많습니다. 둘을 맞추지 않으면 핸들 계산과 실제 화면이 어긋납니다.

가능한 정책은 이런 식입니다.

  • 항상 top-left 기준
  • 항상 center 기준
  • 사용자가 바꿀 수 있는 custom pivot

중요한 건 하나를 고르고 명시하는 것입니다. CSS 기본값에 조용히 맡겨두면, 나중에 rotation handle이 엉뚱한 곳을 기준으로 돌아갑니다.

데모에서 볼 것

데모에서는 rotate 후 translate와 translate 후 rotate를 비교하고 matrix readout을 확인합니다.

오늘의 핵심은 transform이 “무엇을 하느냐”만큼 “언제 하느냐”와 “어디를 기준으로 하느냐”가 중요하다는 점입니다. 순서와 origin을 잡으면 transform이 한결 얌전해집니다.

Edit this page
최근 수정: 26. 5. 14. PM 5:45
Contributors: easylogic
Prev
CSS matrix(a,b,c,d,e,f)
Next
local, world, screen 좌표계