웹 애니메이션 - 이제 Chrome 36에서element.animate()가 제공됩니다.

브렌든 케니
브렌든 케니

웹의 애니메이션은 한때 JavaScript의 한 분야였지만, 세계가 모바일로 이동함에 따라 애니메이션은 선언적 구문과 관련하여 CSS로 이동되었고 브라우저가 이를 통해 만들 수 있었습니다. 모바일에서는 항상 60fps가 목표이므로, 브라우저에서 효율적으로 표시하는 방법을 알고 있는 범위를 벗어나지 않는 것이 좋습니다.

자바스크립트 기반 애니메이션을 더 효율적으로 만드는 도구가 늘어나고 있지만, 가장 중요한 점은 선언적 애니메이션과 명령형 애니메이션의 통합입니다. 선언적 애니메이션과 명령형 애니메이션의 통합은 가장 명확한 코드를 토대로 결정되며 한 형식에서는 가능한 것은 물론 다른 방식으로는 불가능할 수도 있습니다.

웹 애니메이션은 이 호출에 응답을 하며 첫 번째 부분은 Chrome 36에 element.animate() 형식으로 출시되었습니다. 이 새로운 함수를 사용하면 순수하게 자바스크립트로 애니메이션을 만들고 CSS 애니메이션 또는 전환만큼 효율적으로 실행할 수 있습니다. 실제로 Chrome 34부터는 똑같은 웹 애니메이션 엔진이 이러한 모든 메서드를 구동합니다.

구문은 간단하며 CSS 전환 또는 애니메이션을 작성해 봤다면 관련 부분이 익숙할 것입니다.

element.animate([
    {cssProperty: value0},
    {cssProperty: value1},
    {cssProperty: value2},
    //...
], {
    duration: timeInMs,
    iterations: iterationCount,
    delay: delayValue
});

이 새로운 함수의 가장 큰 이점은 이전에는 부드럽고 버벅거림이 없는 애니메이션을 만들기 위해 거쳐야 했던 번거로운 작업을 없었다는 것입니다.

일례로 작년에 출시한 Santa Tracker에서는 눈이 계속 내리도록 만들고자 했으며 효과적으로 수행할 수 있도록 CSS를 통해 애니메이션을 적용하기로 결정했습니다.

하지만 화면과 장면 자체에서 발생하는 이벤트를 기반으로 눈의 수평 위치를 동적으로 선택하고자 했으며, 당연히 눈이 내리는 높이 (사용자 브라우저 창의 높이)는 실제로 달릴 때까지 알 수 없습니다. 즉, 런타임에 CSS 애니메이션을 작성하는 작업이 빠르게 복잡해지기 때문에 실제로 CSS 전환을 사용해야 했습니다. 눈송이가 수백 개 있으면 수백 개의 새로운 스타일 규칙이 필요합니다.

그래서 다음과 같은 접근 방식을 취했습니다.

snowFlake.style.transform = 'translate(' + snowLeft + 'px, -100%)';
// wait a frame
snowFlake.offsetWidth;
snowFlake.style.transitionProperty = 'transform';
snowFlake.style.transitionDuration = '1500ms';
snowFlake.style.transform = 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)';

키는 '프레임 대기' 주석에 있습니다. 전환을 성공적으로 시작하려면 브라우저에서 요소가 시작 위치에 있음을 확인해야 합니다. 몇 가지 방법이 있습니다. 가장 일반적인 방법 중 하나는 브라우저가 레이아웃을 계산하도록 하는 요소 속성 중 하나에서 읽는 것입니다. 이렇게 하면 종료 위치로 전환하기 전에 브라우저에 시작 위치가 있다는 것을 알 수 있습니다. 이 방법을 사용하면 브라우저 내부 기능에 대한 뛰어난 지식은 물론, 키를 입력할 때마다 더러운 느낌을 받을 수 있습니다.

반면에 상응하는 element.animate() 호출은 의도된 것을 정확하게 말해서 더 명확할 수 없습니다.

snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);

더 많은 옵션이 있습니다. 웹 애니메이션도 CSS의 해당 CSS와 마찬가지로 지연되고 반복될 수 있습니다.

snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], {
    duration: 1500,
    iterations: 10,
    delay: 300
});

AnimationPlayer

element.animate()는 실제로 AnimationPlayer 객체를 반환합니다. 이 객체는 웹 애니메이션 사양이 더 많이 출시됨에 따라 점점 더 중요해집니다. JavaScript와 CSS로 만든 애니메이션에는 모두 연결된 AnimationPlayer가 있으므로 유용하고 흥미로운 방식으로 원활하게 결합할 수 있습니다.

하지만 현재 AnimationPlayer에는 두 가지 기능만 있으며, 둘 다 매우 유용합니다. 언제든지 AnimationPlayer.cancel()를 사용하여 애니메이션을 취소할 수 있습니다.

var player = snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);
// less than 1500ms later...changed my mind
player.cancel();

또한, 이전에 CSS 애니메이션 또는 전환을 중심으로 애니메이션 시스템을 빌드하려고 시도한 모든 사용자를 위해, 웹 애니메이션은 완료 시 항상 이벤트를 실행합니다.

var player = snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);
player.onfinish = function(e) {
    console.log('per aspera ad terra!');
}

사용해 보기

이 기능은 모두 Chrome 36에 제공되며 오늘 베타로 전환됩니다. 사용해 보려면 Chrome 36의 기본 구현으로 작업해 보세요. 하지만 최신 상시 브라우저로 전체 웹 애니메이션 사양에서 상당 부분을 차지하는 웹 애니메이션 폴리필을 사용할 수 있습니다.

눈 효과의 데모를 통해 element.animate()기본 버전과 polyfill을 모두 사용해 볼 수 있습니다.

의견을 알려 주세요

하지만 실제로는 다음 기능의 미리보기이며, 개발자의 피드백을 즉시 받기 위해 특별히 출시되고 있습니다. 모든 사용 사례에 도달했는지 아니면 현재 애니메이션 API의 모든 거친 면을 보완했는지 아직 확신할 수 없습니다. 개발자 여러분께서 직접 사용해 보시고 의견을 알려주셔야만 제대로 대처할 수 있습니다.

이 게시물의 댓글은 물론 가치가 있으며 표준 자체에 대한 의견은 public-fx 메일링 리스트를 통해 CSS 및 SVG 작업 그룹으로 전달할 수 있습니다.

2014년 10월 업데이트: Chrome 39에서는 play(), pause(), reverse() 등 재생 제어와 관련된 몇 가지 추가 메서드를 지원합니다. 또한 currentTime 속성을 통해 애니메이션 타임라인의 특정 지점으로 이동할 수 있습니다. 새 데모에서 이 기능의 작동 방식을 확인할 수 있습니다.

이 게시물에 도움을 주신 애디 오스마니와 맥스 하인리츠님께 감사드립니다.