이번 팀 프로젝트에서 캐릭터를 랜덤으로 생성해주는 기능이 있었는데 스프라이트 이미지의 위치를 조정해서 눈과 입을 정할 수 있게 만들어 주었다.
부드러운 전환효과를 주기위해서 transition 속성을 사용했는데 캐릭터 다시 만들기 버튼을 연속으로 클릭하는 경우 제대로 작동하지 않는 문제가 있었다.
이 문제를 transitionend 이벤트를 사용해서 해결하게 되어서 기록하고자한다.
transitionend 이벤트
transitionend 이벤트는 CSS transition 이 완료되면 발생한다. transition 속성이 제거되거나 display가 none으로 설정된 경우와 같이 완료 전에 transition이 제거된 경우에는 이벤트가 생성되지 않는다.
위의 코드는 버튼을 클릭하면 active 클래스를 토글해준다.
active 클래스가 있으면 색깔과 크기가 변하면서 회전하는 css가 적용되어 있다.
버튼을 트랜지션이 끝나기전에 누르게 되면 회전하던 박스가 회전 끝내지 못하는 문제가 있다.
이 문제를 해결하기 위해서는 트랜지션이 종료되기 전에 발생하는 클릭이벤트를 무시해줘야한다.
const box = document.querySelector('.box');
const button = document.querySelector('button');
const clickEvent = () => {
button.onclick = null;
box.textContent = '회전하는중';
box.classList.toggle('active');
};
button.onclick = clickEvent;
box.ontransitionend = () => {
box.textContent = '완료';
button.onclick = clickEvent;
}
클릭이벤트가 발생하면 바로 null을 할당해서 이벤트핸들러를 제거하고
transitionend 이벤트가 발생했을때 다시 이벤트핸들러를 등록해준다.
이렇게 되면 첫번째 클릭이벤트가 발생한 이후에 발생한 발생한 클릭이벤트는 무시되고 버튼을 여러번 클릭해도 트랜지션이 종료된 후의 클릭에만 회전하게된다.
const box = document.querySelector('.box');
const button = document.querySelector('button');
let isMoving = false;
button.onclick = () => {
if (!isMoving) {
box.textContent = '회전하는중';
box.classList.toggle('active');
}
isMoving = true;
};
box.ontransitionend = () => {
isMoving = false;
box.textContent = '완료';
};
isMoving 이라는 변수를 사용해서 isMoving이 false일때만 클래스를 토글해주는 방법이다.
우리 프로젝트에서는 두번째 방법을 적용하였다.
첫번째 방법을 사용하게 되면 키보드 이벤트에도 동일하게 이벤트핸들러를 제거했다가 다시 등록해줘야하기때문에 변수를 사용하는 방법이 더 좋다고 생각했다.
또 isMoving이라는 변수이름을 사용했기때문에 코드의 가독성도 좋다고 생각했다.
transition 속성을 자주 사용하는데 이런 이벤트를 알고 있다면 개발할때 유용하게 사용될것 같다.
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/transitionend_event
모던 자바스크립트 Deep Dive