0824 개발일지

학습내용

자바스크립트 주요기능 구현하기(3): Snackbar, Accordian, Slide
github커밋

1. SnackBar

  • 목표: 버튼 클릭 시 화면 아래 메시지가 올라오면서 페이드인했다가 2초 뒤 페이드아웃하며 아래로 사라지게 하기

애니메이션 만들기

  • visibility는 transition으로 부드럽게 전환 안 됨 -> opacity 사용
  • animation-fill-mode:forwards: 애니메이션 동작 완료 후 마지막 to 유지하기
  • @keyframes로 fadeIn, fadeOut 만들어주었다. 하나의 @keyframe에서 from, to로 같은 효과 만들 수 있을지 생각해봤는데 나타나서 해당 자리에 멈춰서서 보이는 부분을 만드려면 더 많은 keyframe가 필요할 것 같았다.
  • animation-delay
#snackbar.show {
    visibility: visible;
    opacity: 1;
    animation: fadeIn 0.5s , fadeOut 0.5s 2.5s forwards;
}

html onclick 함수 전달해서 구현하기

  • setTimeout()을 이용해 일정 시간이 지나면 클래스를 삭제해 보이지 않도록 만들어주었다.
  • 이렇게 만든 함수의 함수명을 html태그 onclick 속성값으로 전달해주면 해당 태그 클릭 시 함수를 호출할 수 있다.
function snackBarFunc() {
    var snackBar = document.getElementById('snackbar');
    snackBar.classList.add('show');

    // 시간을 2.5초보다 긴 3.5초 전달
    setTimeout(function() {
        snackBar.classList.remove('show');
    }, 3500);
};
<button type="button" onclick="snackBarFunc()">Show</button>

addEventListener로 만들기

  • 원래 하던 방식으로 구현하는 것도 한 번 해 보았다. 이미 만들어진 함수가 있기 때문에 이벤트리스너 인자로 전달해주는 부분만 추가하였다.
  • html 태그의 onclick은 삭제해준다.
var btnShow = document.querySelector('button');
btnShow.addEventListener('click', snackBarFunc);

2. Accordian

목표 1: 클릭하면 열리는 메뉴 만들기

  • max-height: 0: 이전 snackbar에선 opacity:0을 사용해 안 보이게 만들었다면, 이번엔 최대 높이값을 조정하여 영역이 자리를 차지하지 않고 안 보이도록 만들었다.
.panel {
    max-height: 0;
    transition: max-height 0.2s linear;
}
  • toggle() 사용해 클래스 있으면 삭제하고 없으면 추가
  • nextElementSibling: 현재 선택된 태그 바로 다음 형제 태그
  • scrollHeight: 현재 태그 높이값 확인 (스크롤바 없는 전체 높이값)
  • maxHeight에 새로운 값 넣는 삼항 연산자 잘 안되는 문제 있었는데 scrollHeight에 px 안 붙여서 그런거였다.
btns.forEach(function(btn) {
    btn.addEventListener('click', function() {
        this.classList.toggle('active');

        var panel = this.nextElementSibling;

        panel.style.maxHeight = (panel.style.maxHeight) 
          ? null : panel.scrollHeight + 'px';
    });
});

목표 2: 클릭하면 현재 메뉴만 열리고 나머지 메뉴 접기

  • 이전 배경색 바뀌는 메뉴 혼자 만들 때 current 변수 이용해서 기존 메뉴 클래스 삭제하는 기능을 이미 구현했기 때문에 이번에도 비슷하게 시도함.
  • 이벤트리스너에 익명함수 말고 별도 함수 만들어서 전달해주려고 하니 함수 아나에서 클릭한 객체 접근하는 방법을 까먹어서 약간 헤맸다. e.target을 기억해내서 사용했다.
  • 현재 열린 토글이 클릭한 토글과 동일하면 클래스 삭제하지 않음->토글 과정으로 삭제되도록 함 current.length>0 && current[0]!==e.target
// 최종
btns.forEach(function(btn) {
    btn.addEventListener('click', showOnlyOne);
});
function showOnlyOne (e) {
    var current = document.querySelectorAll('.accordian.active');

    if(current.length>0 && current[0]!==e.target) {
        current[0].classList.remove('active');
        current[0].nextElementSibling.style.maxHeight = null;
        console.log(current[0].classList);
    }
    togglePanel(e);
};
function togglePanel (e) {
    e.target.classList.toggle('active');
    var panel = e.target.nextElementSibling;
    panel.style.maxHeight = (panel.style.maxHeight) ? null : panel.scrollHeight + 'px';
};

3. Slide

  • 목표: 하나의 이미지 영역에 서로 다른 이미지 교차되면서 페이드인-아웃 슬라이드

슬라이드 만들기

  1. 현재 보이는 슬라이드 선택
var currentSlide = document.querySelector('.item.show');
  1. 현재 보여지고 있는 슬라이드 있는지 여부 따지기
if(currentSlide) {
  // 보여지는 슬라이드 있으면 삭제하기
} else {
  // 없으면 첫 슬라이드 보여주기
}
  1. 현재 보여지고 있는 슬라이드 있으면 그 중 다음 슬라이드 있는지 여부 따지기
if(currentSlide) {
  // 보여지는 슬라이드 있으면 삭제
  if(nextSlide) {
    // 다음 슬라이드 있으면 보여주기
  } else {
    // 다음 슬라이드 없으면 첫 슬라이드 보여주기
  }
} else {
  // 없으면 첫 슬라이드 보여주기
}

setInterval() vs setTimeout()

  • setInterval(콜백함수, 시간간격): 일정 시간 간격을 두고 함수를 무한 반복 실행. 함수를 변수에 담아 clearInterval에 인자로 넘겨주면 특정 시간 뒤 멈추기 가능
  • setTimeout(콜백함수, 딜레이): 일정 시간이 지난 후에 함수를 한 번 실행. 반복하려면 내부에서 자신 호출 필요
// 1초마다 한 번씩 슬라이드 변경되다가 5초 지나면 정지하고 end 출력
let doSlide = setInterval(slide, 1000);

setTimeout(function() {
    clearInterval(doSlide);
    document.querySelector('.item.show').textContent = 'end';
}, 5000);

어려웠던 점

  1. SnackBar 움직임을 애니메이션으로 구현할 때, fade 효과 사이 시간에 메시지가 안 보이거나, fadeOut 후 메시지가 잠시 보였다가 사라지는 등의 에러가 있었다.
    2.setInterval() 함수가 나왔는데, 이전 사용했던 setTimeOut()과 어떤 점이 다른지 헷갈려서 따로 검색해보았다.
  2. 아코디언 메뉴 구현할 때 다른 영역 선택 시 기존 영역 접히게 만드는 기능을 구현하고 싶었는데 기존 영역 다시 클릭 시 접히지 않는 문제가 있었다.
  3. animation-delay 관련해서 여러 개의 애니메이션에 딜레이가 있으면, 그 딜레이 시작 기준점이 이벤트 시작 시점인지 이전 애니메이션이 끝난 시점인지 헷갈렸다.
  4. Slide 만들 때 논리 순서가 좀 헷갈렸다.

해결방법

  1. 아마 예전 방식처럼 addEventListener로 구현하기 위해 만든 별도 클래스에서 opacity를 사용하니 다른 태그에 opacity값이 없어서 꼬인게 아닌가 싶다. snackbar 태그와 show 클래스에 별도로 opacity값을 추가해서 해결하였다.
  2. 검색해보고 따로 정리하였다.
  3. 버튼 접히고 열리는 것을 toggle()로 구현했는데, 기존 버튼 클릭 시 이미 열려있는 기존 버튼을 끄고 다시 toggle()로 열게 되서 결과적으로 변하지 않는 것처럼 보인 것이 문제였다. 기존 버튼 접는 if 문에 조건 추가해서 해결하였다.
  4. 내 추측으론 모든 애니메이션 시작 기준점은 이벤트 시작 시점인 것 같은데, 검색해봐도 명확히 나오지 않아서 멘토님께 질문을 남겼다. 답변이 오면 내용을 추가해야겠다.
  5. 주석, consolo.log를 사용해 과정을 따라가 보았다.

소감

어제처럼 간단한 기능 구현이 다였지만, 강의만 따라가지 않고 여러 가지 변주를 주면서 연습하니 배우는 것이 많았다.

좋은 웹페이지 즐겨찾기