CSS 애니메이션 이벤트와 자바스크립트 연동하기

애니메이션 자바스크립트 이벤트 처리

웹페이지 레이아웃에 적용하는 CSS 애니메이션이나, 배너, 또는 아이콘 애니메이션은 그것만으로도 풍부한 웹페이지를 만드는데 도움을 줍니다. 그리고, 사용자 액션에 반응해서 애니메이션이 동작하도록 하는 것 정도는 체크박스나 마우스호버 속성 등을 이용하면 CSS 만으로 구현을 할 수 있습니다.

그러나, 애니메이션이 시작되거나, 애니메이션이 종료되는 시점에 특정 액션이 동작하도록 하거나 새로운 애니메이션, 또는 UI가 동작하도록 하는 것은 CSS만으로는 구현할 수가 없습니다.

이런 경우에는 자바스크립트의 도움이 필수이며, 자바스크립트와 연동할 수 있도록 웹 표준으로 이벤트를 제공합니다.

애니메이션이 시작되거나 종료되는 시점에 특정 이벤트가 발생하고, 자바스크립트는 이 이벤트를 캐치해서 적당한 시점에 새로운 애니메이션을 실행하거나, UI 동작을 처리할 수 있습니다.

자바스크립트에서 지원하는 CSS 애니메이션 이벤트는 다음과 같습니다.

애니메이션 이벤트 발생 위치
animationstart 애니메이션이 시작되면 발생
animationend 애니메이션이 종료되면 발생
animationiteration 반복 루프를 도는 애니메이션이 루프를 1번 돌 때마다 발생

자바스크립트로는 애니메이션되는 요소를 선택해 애니메이션 이벤트 리스너를 등록하면 됩니다.

element.addEventListener('animationiteration', function(){
});

앞서의 심장이 뛰는 반복 애니메이션의 카운트를 표시하는 자바스크립트 코드를 작성해보겠습니다.

".box" 클래스 블록 태그는 심장이 뛰는 아이콘을 애니메이션 하기 위한 틀이고, ".counter" 클래스는 자바스크립트 이벤트가 실행될 때마다 메시지를 표시하는 메시지 출력용입니다.

<div class="wrap">
    <h3 class="counter"></h3>
    <div class="box"></div>
</div>

심장 아이콘은 아스키ii 아이콘을 가상요소(::before) 로 붙여서 애니메이션(heartbeat)을 추가합니다.

애니메이션은 단순하게 심장 아이콘이 커졌다 작아졌다 하는 키프레임 애니메이션을 만들어 적용합니다.

.wrap{
    width: 300px;
    height: 300px;
    background-color: #f0f0f0;
    border-radius: 30px;
    margin: 0 auto;
    position: relative;
}
.box::before{
    content: '❤';
    position: absolute;
    left:100px;
    top: 100px;
    float: left;
    color: pink;
    font-size: 100px;
    line-height: 1;
    animation: heartbeat 1s 3 ease; /*심장 아이콘 애니메이션 반복 횟수(iterate)는 3회 */
}
.counter{/* 자바스크립트 이벤트 처리 메시지 출력 */
    text-align: center;
    color: pink;
}
/* 크기가 변하는 심장 아이콘 키프레임 애니메이션 */
@keyframes heartbeat {
    0% {
        transform: scale(1.0);
    }
    50% {
        transform: scale(1.3);
    }
    100% {
        transform: scale(1.0);
    }
}

이제 애니메이션이 실행되는데 따라서 자바스크립트 이벤트가 처리되고, 처리된 이벤트에 대한 메시지가 화면에 표시되도록 자바스크립트 코드를 추가합니다.

DOM 생성 후 이벤트 등록이 되도록 "DOMContentLoaded" 이벤트 리스너 안에 애니메이션 이벤트 리스너를 추가합니다. 앞서 CSS 애니메이션 트랜지션(transition) 속성에서 반복 횟수를 3회로 제한했으므로 애니메이션 루프가 3번 실행되고 애니메이션이 정지되며, 애니메이션이 루프를 도는 횟수에 맞춰 메시지가 다르게 출력됩니다.

// DOM 로딩 완료 후 이벤트 처리
document.addEventListener('DOMContentLoaded', function(){
    const heartbeat = document.querySelector('.box');
    const msg = document.querySelector('.counter');
    let beater = 0;
    //이벤트 메시지 출력 함수들
    const iterate = () => {
      beater++;
      msg.innerText = `하트 ${beater} 번 뜀!`;
    }
    const start = () => {
        msg.innerText = `애니메이션 시작!`;
      }
    const end = () => {
        msg.innerText = `애니메이션 종료!`;
    }
    // 애니메이션 이벤트 리스너 등록
    heartbeat.addEventListener('animationstart', start);
    heartbeat.addEventListener('animationend', end);
    heartbeat.addEventListener('animationiteration', iterate);
});