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
- 목표: 하나의 이미지 영역에 서로 다른 이미지 교차되면서 페이드인-아웃 슬라이드
슬라이드 만들기
- 현재 보이는 슬라이드 선택
var currentSlide = document.querySelector('.item.show');
- 현재 보여지고 있는 슬라이드 있는지 여부 따지기
if(currentSlide) {
// 보여지는 슬라이드 있으면 삭제하기
} else {
// 없으면 첫 슬라이드 보여주기
}
- 현재 보여지고 있는 슬라이드 있으면 그 중 다음 슬라이드 있는지 여부 따지기
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);
어려웠던 점
- SnackBar 움직임을 애니메이션으로 구현할 때, fade 효과 사이 시간에 메시지가 안 보이거나, fadeOut 후 메시지가 잠시 보였다가 사라지는 등의 에러가 있었다.
2.setInterval()
함수가 나왔는데, 이전 사용했던 setTimeOut()
과 어떤 점이 다른지 헷갈려서 따로 검색해보았다.
- 아코디언 메뉴 구현할 때 다른 영역 선택 시 기존 영역 접히게 만드는 기능을 구현하고 싶었는데 기존 영역 다시 클릭 시 접히지 않는 문제가 있었다.
animation-delay
관련해서 여러 개의 애니메이션에 딜레이가 있으면, 그 딜레이 시작 기준점이 이벤트 시작 시점인지 이전 애니메이션이 끝난 시점인지 헷갈렸다.
- Slide 만들 때 논리 순서가 좀 헷갈렸다.
해결방법
- 아마 예전 방식처럼 addEventListener로 구현하기 위해 만든 별도 클래스에서 opacity를 사용하니 다른 태그에 opacity값이 없어서 꼬인게 아닌가 싶다. snackbar 태그와 show 클래스에 별도로 opacity값을 추가해서 해결하였다.
- 검색해보고 따로 정리하였다.
- 버튼 접히고 열리는 것을 toggle()로 구현했는데, 기존 버튼 클릭 시 이미 열려있는 기존 버튼을 끄고 다시 toggle()로 열게 되서 결과적으로 변하지 않는 것처럼 보인 것이 문제였다. 기존 버튼 접는 if 문에 조건 추가해서 해결하였다.
- 내 추측으론 모든 애니메이션 시작 기준점은 이벤트 시작 시점인 것 같은데, 검색해봐도 명확히 나오지 않아서 멘토님께 질문을 남겼다. 답변이 오면 내용을 추가해야겠다.
- 주석, consolo.log를 사용해 과정을 따라가 보았다.
소감
2.
setInterval()
함수가 나왔는데, 이전 사용했던 setTimeOut()
과 어떤 점이 다른지 헷갈려서 따로 검색해보았다.animation-delay
관련해서 여러 개의 애니메이션에 딜레이가 있으면, 그 딜레이 시작 기준점이 이벤트 시작 시점인지 이전 애니메이션이 끝난 시점인지 헷갈렸다.- 아마 예전 방식처럼 addEventListener로 구현하기 위해 만든 별도 클래스에서 opacity를 사용하니 다른 태그에 opacity값이 없어서 꼬인게 아닌가 싶다. snackbar 태그와 show 클래스에 별도로 opacity값을 추가해서 해결하였다.
- 검색해보고 따로 정리하였다.
- 버튼 접히고 열리는 것을 toggle()로 구현했는데, 기존 버튼 클릭 시 이미 열려있는 기존 버튼을 끄고 다시 toggle()로 열게 되서 결과적으로 변하지 않는 것처럼 보인 것이 문제였다. 기존 버튼 접는 if 문에 조건 추가해서 해결하였다.
- 내 추측으론 모든 애니메이션 시작 기준점은 이벤트 시작 시점인 것 같은데, 검색해봐도 명확히 나오지 않아서 멘토님께 질문을 남겼다. 답변이 오면 내용을 추가해야겠다.
- 주석, consolo.log를 사용해 과정을 따라가 보았다.
소감
어제처럼 간단한 기능 구현이 다였지만, 강의만 따라가지 않고 여러 가지 변주를 주면서 연습하니 배우는 것이 많았다.
Author And Source
이 문제에 관하여(0824 개발일지), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@lee_yesol421/0824-개발일지저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)