3D transform은 3차원 공간을 사용하기 때문에 2D transform보다 더 다양한 변환과 복잡한 애니메이션을 구현할 수 있다.
예시로 Card Flip 애니메이션 을 구현해 보자. 🔗애니메이션 보러가기🔗
마크업:
<div class="scene"> <div class="card"> <div class="card__face card__face--front">front</div> <div class="card__face card__face--back">back</div> </div> </div>
-> .scene은 3D 공간, .card는 3D 오브젝트, 그리고 두개로 나눠진 .card__face는 뒤집을 때 마다 보여질 카드의 겉면이다.
CSS:
.scene { width: 200px; height: 260px; perspective: 600px; }
-> .scene에 perspective를 줘서 3D 공간에서 변환할 수 있도록 한다.
CSS:
.card { width: 100%; height: 100%; position: relative; transition: transform 1s; transform-style: preserve-3d; }
-> transform-style: preserve-3d 가 없으면 카드의 면이 부모와 함께 평평해지고 뒷면의 회전이 무효화된다.
CSS:
.card__face { position: absolute; height: 100%; width: 100%; backface-visibility: hidden; }
-> 3D 공간에서 면의 위치를 지정하려면
position: absolute
를 사용하여 2D에서 해당 위치를 재설정해야한다.
CSS:
.card__face--front { background: red; } .card__face--back { background: blue; transform: rotateY( 180deg ); }
->
.card__face--back
를 뒤집기 위해 3D transform인 `rotateY(180deg)를 추가해준다.
CSS:
.card.is-flipped { transform: rotateY(180deg); }
-> 면이 제자리에 있는 경우, .card는 뒤집을 때 해당 스타일이 필요하다.
마지막으로 JS에서 클래스를 토글해주기
var card = document.querySelector('.card'); card.addEventListener( 'click', function() { card.classList.toggle('is-flipped'); });
애니메이션을 구현하다 보면 매끄럽지 못하고 부자연스러운 현상이 나타날 때가 있는데, 이런 문제를 jank라고 한다.
jank는 reflow(리플로우)와 repaint(리페인트)라는 과정때문에 일어나는데, 이것은 처음 화면에 보이는 요소들이 이동을 하게 되면 요소의 크기, 간격 등을 다시 계산해서 화면에 나타나는 과정이다. 한 번에 많은 요소들의 위치가 변하게 되면 브라우저가 그 속도를 따라가지 못해서 끊겨보일 수 있다.
이러한 문제를 해결하기 위해 최적화가 필요한데, 애니메이션 최적화는 애니메이션을 더 부드럽게 실행하고, 성능을 향상시키며 시스템을 절약하는 과정을 말한다.
animation 최적화 기법에는 여러가지가 있다.
브라우저 렌더링의 순서를 이해하면 어떤 속성을 사용해야 더 빠르게 렌더링을 끝낼 수 있는지 알 수 있다.
웹 브라우저 스타일 적용 순서
여기서, 각각의 순서에 해당되는 속성들이 정해져 있다.
Style = 클래스 선택자나 ID 선택자를 기반으로 어떤 CSS 규칙이 어떤 요소에 적용되는지 파악
⬇
Layout = 요소가 차지하는 공간과 화면의 위치를 계산
ex) margin, padding, width, height, top, display, position...
⬇
Paint = 픽셀을 채우는 단계로 텍스트, 색상, 이미지 등 시각적인 부분을 그리는 작업
ex) background, color, box-shadow...
⬇
Composite = 순서에 따라 모든 레이어를 화면에 나타냄
ex) transform, opacity
만약에 총 100px을 왼쪽으로 옮기는 애니메이션에서 0.1px씩 옮겨진다고 가정하면 0.1px 마다 Layout ➡ Paint ➡ Composite 순서를 거치는 것 보다 Composite 만 거치는 것이 훨씬 빠를 것이다. 그래서 transform을 사용하면 브라우저의 빠른 렌더링에 도움을 줄 수 있다.
❗️주의할 점은
가끔은 Layout을 적용하는 요소를 사용해야할 때가 있다. 이 때 애니메이션 효과를 가질 요소만 움직이고 나머지는 움직이지 않는다면 reflow 현상이 완화될 수 있다.
방법은
position: absolute
OR
position: fixed
-> 문서의 흐름에서 제거되고, 다른 요소들에게 영향을 미치지 않는다.
requestAnimationFrame()함수는 브라우저에게 애니메이션을 수행하고 다음 리페인트(repaint) 이전에 지정된 함수를 호출하여 애니메이션을 업데이트 하도록 요청하는 방법이다.
function animate() { // animation 코드 작성 requestAnimationFrame(animate); } animate();