6-3 Transform 3D

perspective (원근)#

3D 를 나타내는 CSS 속성 중 하나이다. image

원근의 거리

  • 모니터에서 사람눈까지의 거리

perspective:600px

  • 잠정적으로 나의 눈과 모니터 사이의 거리를 600px 보겠다.
  • 픽셀값이 커질수록 똑같은 물건이 작아보일 것이다.

어안렌즈 효과

  • 단지 크기의 차이의 의미가 있는 것이 아니다.
  • 앞에 있는 것은 크게 보이는데, 조금만 옆에 있어도 대게작아보인다.
  • 멀리있으면 왜곡이 덜한데 가까이 가면 왜곡이 심해진다.
  • 멀리있으면 있을수록 마치 2D 처럼 flat 하게 보인다.
  • 가까이 와야지만 3D 같아 보이고 왜곡효과가 커진다.

perspective-origin#

변형을 할 때 어디를 바라보고 perspective 를 인식할 것이냐 image

perspective 는 거리만 나타낸다고 보면, 모니터 한 가운데를 보고있다고 가정한다.

perspective-origin 은 좌상단을 볼 때, 우 하단을 볼 때 이런 개념이 가능하다.

예제#

perspective-origin 과 perspective-origin 를 적용하였다.

<html>
<body>
<div class="test"></div>
</body>
<style>
@keyframes origin {
0% { perspective-origin: 0% 50% }
50% { perspective-origin: 100% 50% }
100% { perspective-origin: 0% 50% }
}
@keyframes spin {
100% { transform: rotateX(360deg)}
}
body, html{ height: 100% }
body { perspective: 600px; background:#404040; animation: origin 10s linear infinite}
.test {
width: 500px; height: 500px; background: #aaa;
position: absolute; left: 50%; top:50%; margin-left:-250px; margin-top: -250px;
animation: spin 30s linear infinite;
}
</style>
</html>

spin 만 적용한 경우

<html>
<body>
<div class="test"></div>
</body>
<style>
@keyframes spin {
100% { transform: rotateX(360deg)}
}
body, html{ height: 100% }
body {
perspective: 600px; background:#404040;
}
.test {
width: 500px; height: 500px; background: #aaa;
position: absolute; left: 50%; top:50%; margin-left:-250px; margin-top: -250px;
animation: spin 30s linear infinite;
}
</style>
</html>

body 에 origin animation 만 넣은 상태는 static 하다.

  • 그러나 gpu 가 그린다.
  • post process 로 밀어버릴려고 속성을 주는 경우도 있다.

transform-style#

DOM 의 tree 구조는 3D 의 트리구조가 아니다. fragment 단계 까지만 영향을 끼친다. image

부모가 회전했을 때, 자식도 회전하면 계층구조가 3D 에도 반영됬다고 할 수 있다.

transform-style:preserve-3d 값을 쓰면, 부모의 3D 관련된 모든 속성을 이어 받을 수 있다.

transform-origin#

실제 변형이 일어날 때의 위치를 정한다.

image

<html>
<body>
<div class="wrapper" style="left:10%; top:50%;" >
<div class="test" style="transform-origin:0% 0% 0"></div>
</div>
<div class="wrapper" style="left:20%; top:50%;" >
<div class="test" style="transform-origin:50% 50%"></div>
</div>
<div class="wrapper" style="left:30%; top:50%;" >
<div class="test" style="transform-origin:0% 100%"></div>
</div>
<div class="wrapper" style="left:40%; top:50%;" >
<div class="test" style="transform-origin:0% 100%"></div>
</div>
<div class="wrapper" style="left:50%; top:50%;" >
<div class="test" style="transform-origin:center"></div>
</div>
<div class="wrapper" style="left:60%; top:50%;" >
<div class="test" style="transform-origin:top left;"></div>
</div>
<div class="wrapper" style="left:70%; top:50%;" >
<div class="test" style="transform-origin:50px 50px;"></div>
</div>
<div class="wrapper" style="left:80%; top:50%;" >
<div class="test" style="transform-origin:bottom right 60px;"></div>
</div>
</body>
<style>
@keyframes spin {
100% { transform: rotateX(360deg)}
}
body, html{ height: 100% }
.wrapper {
perspective: 800px;
background:#404040;
width: 120px; height: 120px;
position: absolute;
}
.test {
width: 120px; height: 120px;
background: #aaa;
animation: spin 4s linear infinite;
}
</style>
</html>
<div class="wrapper-origin" style="left:0%; top:50%;" >
<div class="test-origin" style="transform-origin:0% 0% 0"></div>
</div>
<div class="wrapper-origin" style="left:30%; top:50%;" >
<div class="test-origin" style="transform-origin:50% 50%"></div>
</div>
<div class="wrapper-origin" style="left:60%; top:50%;" >
<div class="test-origin" style="transform-origin:0% 100%"></div>
</div>
<div class="wrapper-origin" style="left:0%; top:50%;" >
<div class="test-origin" style="transform-origin:center"></div>
</div>
<div class="wrapper-origin" style="left:30%; top:50%;" >
<div class="test-origin" style="transform-origin:top left;"></div>
</div>
<div class="wrapper-origin" style="left:0%; top:50%;" >
<div class="test-origin" style="transform-origin:50px 50px;"></div>
</div>
<div class="wrapper-origin" style="left:30%; top:50%;" >
<div class="test-origin" style="transform-origin:bottom right 60px;"></div>
</div>

backface-visibility/frontface-visibility#

3D 의 앞면/뒷면을 보이게 할지 말지를 결정

그리는 면을 줄이면 사용하는 리소스가 줄어준다.

  • backface 는 일반적으로 활성화 되어있기 때문에 비활성화 시켜야 한다.
<html>
<body>
<div class="test"></div>
</body>
<style>
@keyframes origin {
0% { perspective-origin: 0% 50% }
50% { perspective-origin: 100% 50% }
100% { perspective-origin: 0% 50% }
}
@keyframes spin {
100% { transform: rotateX(360deg)}
}
body, html{ height: 100% }
body { perspective: 600px; background:#404040; animation: origin 10s linear infinite}
.test {
width: 500px; height: 500px; background: #aaa;
position: absolute; left: 50%; top:50%; margin-left:-250px; margin-top: -250px;
animation: spin 30s linear infinite;
backface-visibility: hidden;
}
</style>
</html>
tip

나머지 javascript 의 최적화가 의미가 없을정도( ~5% )로 그림 그리는 것이 부하가 가장크다. 렌더링 로직의 개선이 중요하다.

Reference#

Last updated on