약속으로 애니메이션 조정, 교체 가능한 애니메이션으로 성능 개선, 복합 모드로 더 부드러운 애니메이션 등
게시일: 2020년 5월 27일
애니메이션을 올바르게 사용하면 브랜드에 대한 사용자 인식과 기억을 개선하고, 사용자 작업을 안내하며, 사용자가 애플리케이션을 탐색하는 데 도움을 주어 디지털 공간에서 맥락을 제공할 수 있습니다.
Web Animations API는 개발자가 JavaScript로 명령형 애니메이션을 작성할 수 있는 도구입니다. CSS 애니메이션과 전환 구현을 모두 뒷받침하고 향후 효과를 개발할 수 있도록 하며 기존 효과를 구성하고 타이밍을 지정할 수 있도록 작성되었습니다.
Firefox 및 Safari는 이미 전체 사양 기능을 구현했지만 Chromium 84에서는 이전에 지원되지 않았던 여러 기능을 Chrome 및 Edge에 도입하여 교차 브라우저 상호 운용성을 지원합니다.
시작하기
@keyframe
규칙을 사용해 본 적이 있다면 Web Animations API를 사용하여 애니메이션을 만드는 것이 매우 익숙할 것입니다. 먼저 키프레임 객체를 만들어야 합니다. CSS에서는 다음과 같이 표시될 수 있습니다. 이렇게
@keyframes openAnimation {
0% {
transform: scale(0);
}
100% {
transform: scale(1);
}
}
JavaScript에서는 이렇게 표시됩니다.
const openAnimation = [
{ transform: 'scale(0)' },
{ transform: 'scale(1)' },
];
CSS에서 애니메이션 매개변수를 설정하는 위치는 다음과 같습니다.
.modal {
animation: openAnimation 1s 1 ease-in;
}
JS에서 다음과 같이 설정합니다.
document.querySelector('.modal').animate(
openAnimation, {
duration: 1000, // 1s
iterations: 1, // single iteration
easing: 'ease-in' // easing function
}
);
코드의 양은 거의 동일하지만 JavaScript를 사용하면 CSS만으로는 얻을 수 없는 몇 가지 강력한 기능을 활용할 수 있습니다. 여기에는 효과 시퀀스 기능과 재생 상태에 대한 향상된 제어 기능이 포함됩니다.
element.animate()
이후
그러나 이번 업데이트로 Web Animations API는 더 이상 element.animate()
를 사용하여 만든 애니메이션으로 제한되지 않습니다. CSS 애니메이션과 전환도 조작할 수 있습니다.
getAnimations()
는 element.animate()
를 사용하여 생성되었는지 또는 CSS 규칙(CSS 애니메이션 또는 전환)을 사용하여 생성되었는지와 관계없이 요소의 모든 애니메이션을 반환하는 메서드입니다. 다음은 이러한 과정을 보여주는 예시입니다.
먼저 전환의 키프레임을 "get"
하여 전환의 시작 위치를 결정합니다. 그런 다음 두 가지 새로운 불투명도 애니메이션을 만들어 크로스 페이드 효과를 사용 설정합니다. 크로스페이드가 완료되면 사본을 삭제합니다.
프라미스로 애니메이션을 조정하는 방법
이제 Chromium 84에서는 약속과 함께 사용할 수 있는 두 가지 메서드인 animation.ready
및 animation.finished
가 있습니다.
animation.ready
를 사용하면 대기 중인 변경사항이 적용될 때까지 (즉, 재생 및 일시중지와 같은 재생 컨트롤 메서드 간 전환) 기다릴 수 있습니다.animation.finished
는 애니메이션이 완료될 때 커스텀 JavaScript 코드를 실행하는 수단을 제공합니다.
계속해서 예시로 돌아가 animation.finished
를 사용하여 조정된 애니메이션 체인을 만듭니다. 여기서는 세로 변환(scaleY
) 다음에 가로 변환(scaleX
)이 적용되고 하위 요소의 불투명도가 변경됩니다.
const transformAnimation = modal.animate(openModal, openModalSettings);
transformAnimation.finished.then(() => { text.animate(fadeIn, fadeInSettings)});
체인의 다음 애니메이션 세트를 실행하기 전에 animation.finished.then()
를 사용하여 이러한 애니메이션을 연결했습니다. 이렇게 하면 애니메이션이 순서대로 표시되고 속도 및 이징과 같은 다양한 옵션을 설정하여 서로 다른 타겟 요소에 효과를 적용할 수도 있습니다.
이 방법은 CSS 내에서, 특히 고유하면서도 시퀀싱된 애니메이션을 여러 요소에 적용하는 경우 재생성하기가 번거로울 수 있습니다. 시퀀스에서 애니메이션을 트리거하기 전에 @keyframe
를 사용하고, 애니메이션을 배치할 올바른 타이밍 비율을 정렬하고, animation-delay
를 사용해야 합니다.
예: 재생, 일시중지, 되감기
열 수 있는 물체가 닫혀야 함 다행히 Chromium 39부터 Web Animations API를 통해 애니메이션을 재생, 일시중지, 역재생할 수 있습니다.
이전에 표시된 애니메이션을 가져와 .reverse()
를 사용하여 버튼을 다시 클릭할 때 부드러운 반전 애니메이션을 제공할 수 있습니다. 이렇게 하면 모달에 더 원활하고 문맥에 맞는 상호작용을 만들 수 있습니다.
재생 대기 중인 애니메이션 2개(openModal
및 인라인 불투명도 변환)를 만든 다음 애니메이션 중 하나를 일시중지하여 다른 애니메이션이 완료될 때까지 지연시킬 수 있습니다. 그런 다음 프로미스를 사용하여 재생하기 전에 각 작업이 완료될 때까지 기다릴 수 있습니다. 마지막으로 플래그가 설정되어 있는지 확인한 다음 각 애니메이션을 역전시킬 수 있습니다.
예: 부분 키프레임과의 동적 상호작용
selector.animate([{transform: `translate(${x}px, ${y}px)`}],
{duration: 1000, fill: 'forwards'});
이 예시에는 키프레임이 하나만 있고 지정된 시작 위치가 없습니다. 다음은 부분 키프레임을 사용하는 예입니다. 마우스 핸들러는 여기서 몇 가지 작업을 수행합니다. 즉, 새 종료 위치를 설정하고 새 애니메이션을 트리거합니다. 새 시작 위치는 현재 기본 위치에서 추론됩니다.
기존 전환이 실행 중일 때 새 전환을 트리거할 수 있습니다. 즉, 현재 전환이 중단되고 새 전환이 생성됩니다.
교체 가능한 애니메이션을 통한 성능 개선
'mousemove'
와 같은 이벤트를 기반으로 애니메이션을 만들 때 매번 새 애니메이션이 생성되므로 메모리가 빠르게 소모되고 성능이 저하될 수 있습니다. 이 문제를 해결하기 위해 교체 가능한 애니메이션이 Chromium 83에서 도입되어 자동 정리가 가능해졌습니다. 여기서 완료된 애니메이션은 교체 가능한 것으로 플래그가 지정되고 다른 완료된 애니메이션으로 교체되면 자동으로 삭제됩니다. 다음 예를 참고하세요.
elem.addEventListener('mousemove', evt => {
rectangle.animate(
{ transform: translate(${evt.clientX}px, ${evt.clientY}px) },
{ duration: 500, fill: 'forwards' }
);
});
마우스가 움직일 때마다 브라우저는 혜성의 궤적에 있는 각 공의 위치를 다시 계산하고 이 새로운 지점으로 애니메이션을 만듭니다. 이제 브라우저는 다음과 같은 경우 이전 애니메이션을 삭제(교체 사용 설정)하도록 합니다.
- 애니메이션이 완료됩니다.
- 컴포지션 순서에서 더 높은 위치에 있는 애니메이션이 하나 이상 있으며 이 애니메이션도 완료되었습니다.
- 새 애니메이션은 동일한 속성을 애니메이션 처리합니다.
anim.onremove
를 사용하여 카운터를 트리거하고 삭제된 각 애니메이션의 카운터를 집계하여 대체되는 애니메이션의 수를 정확하게 확인할 수 있습니다.
애니메이션을 더욱 세부적으로 제어하는 몇 가지 추가 메서드가 있습니다.
animation.replaceState()
는 애니메이션이 활성 상태인지, 유지되었는지 또는 삭제되었는지 추적하는 수단을 제공합니다.animation.commitStyles()
는 복합 순서에 따라 요소의 모든 애니메이션과 함께 기본 스타일을 기반으로 요소의 스타일을 업데이트합니다.animation.persist()
는 애니메이션을 대체 불가능으로 표시합니다.
합성 모드로 더 부드러운 애니메이션
이제 Web Animations API를 사용하여 애니메이션의 합성 모드를 설정할 수 있습니다. 즉, 기본 모드인 'replace' 외에도 애니메이션을 더하거나 누적할 수 있습니다. 합성 모드를 사용하면 개발자가 고유한 애니메이션을 작성하고 효과가 결합되는 방식을 제어할 수 있습니다. 이제 'replace'
(기본 모드), 'add'
, 'accumulate'
의 세 가지 컴포지트 모드가 지원됩니다.
애니메이션을 합성할 때 개발자는 짧고 고유한 효과를 작성하고 결합된 모습을 볼 수 있습니다. 다음 예에서는 각 상자에 회전 및 크기 조정 키프레임을 적용하고 있으며, 유일하게 조정된 것은 옵션으로 추가된 합성 모드입니다.
기본 'replace'
컴포지션 모드에서 최종 애니메이션은 변환 속성을 대체하고 rotate(360deg) scale(1.4)
에서 종료됩니다. 'add'
의 경우 합성은 회전을 추가하고 크기를 곱하여 최종 상태 rotate(720deg) scale(1.96)
를 만듭니다. 'accumulate'
는 변환을 결합하여 rotate(720deg) scale(1.8)
를 생성합니다. 이러한 복합 모드의 복잡성에 대한 자세한 내용은 웹 애니메이션 사양에서 CompositeOperation 및 CompositeOperationOrAuto 열거형을 참조하세요.
다음 UI 요소 예를 살펴보세요.
여기서는 두 개의 top
애니메이션이 합성됩니다. 첫 번째는 매크로 애니메이션으로 페이지 상단에서 슬라이드 인 효과로 메뉴 자체의 전체 높이만큼 드롭다운을 이동하고 두 번째는 마이크로 애니메이션이 하단을 향해 약간 바운스를 적용합니다. 'add'
복합 모드를 사용하면 더 원활한 전환이 가능합니다.
const dropDown = menu.animate(
[
{ top: `${-menuHeight}px`, easing: 'ease-in' },
{ top: 0 }
], { duration: 300, fill: 'forwards' });
dropDown.finished.then(() => {
const bounce = menu.animate(
[
{ top: '0px', easing: 'ease-in' },
{ top: '10px', easing: 'ease-out' },
{ ... }
], { duration: 300, composite: 'add' });
});
Web Animations API의 향후 계획
이러한 기능은 모두 오늘날 브라우저의 애니메이션 기능에 추가된 흥미로운 기능이며, 앞으로 더 많은 기능이 추가될 예정입니다. 향후 출시될 사양을 확인하여 다음에 출시될 기능에 대해 자세히 알아보세요.