반응형
IntersectionObserver API로 Fade in, Fade out 구현하기
ZUM 기술 블로그를 구경하다 디자인이 깔끔하고 이뻐서 클론해봤다. 정확히는 사이트의 Fade in, Fade out의 동작 방식이 궁금해서 직접 구현해봤다.
근데 이제 UI/UX를 곁들인..
기능 구현 외에도 깔끔한 UI/UX 덕분에 가독성도 좋았다. 뭔가 집중이 된달까..그래서 전체적인 분위기나 모바일 대응도 구현했다.
동작 방식 알아보기
- 해당 블로그는 첫화면에 노출되는 포스트는 shown 클래스를 생성해서 바로 보여주게 된다.
- ➡️ 동적으로 클래스를 만듦
- 그 후 포스트들은 스크롤 다운 시 animate 클래스를 생성해서 보여주게 된다.
- ➡️ moveUp 애니메이션 작동, 포스트가 올라옴
- ➡️ 각각 다른 animation-duration이 적용된다. 랜덤임
- 모든 포스트는 초기값에 opacity: 0이 적용되어 있다.
- 화면의 크기에 따라 첫화면에 노출된 포스트는 shown 클래스 생성
- 첫화면에 노출되지 않은 포스트들은 스크롤 다운 시 animate 클래스 생성
- animate 클래스가 추가된 포스트는 moveUp 애니메이션 작동
여기까지 알아낸 내용을 토대로 기능을 구현했다.
문제 해결하기
클래스가 동적으로 생성되기 때문에 스크롤을 다운한 상태에서 새로고침 시, 그 상태에서 첫화면이 뜨기 때문에 해당 위치의(노출된) 포스트를 바로 보여주고 다른 포스트들은 애니메이션이 구현되어야 한다. 이 부분에 시간을 많이 쓰게 되었다.
const article = document.querySelectorAll('.content');
let className = 'show';
const observerCallback = (entries, observer) => {
entries.forEach(({ isIntersecting, intersectionRatio, target }) => {
if (isIntersecting && intersectionRatio > 0) {
// 처음에 노출된 포스트들은 className이 show
target.classList.add(className);
observer.unobserve(target);
}
});
// 그 후 className은 animate
className = 'animate';
};
const observerOptions = {
root: null,
rootMargin: '0px',
threshold: 0.3,
};
const io = new IntersectionObserver(observerCallback, observerOptions);
articles.forEach((article) => io.observe(article));
구현해놓고 보니 간단해 보이지만 구현하기 전엔 굉장히 막막했다. 코드가 엄청 길어지기도 했었고 동작이 제대로 되지 않아서 고생도 했지만 결과는 만족스러웠다.
이것저것 시도해보다가 결국 컴퓨터가 원하는 답을 얻게 되어서 기분이 좋다. 😁
그리고 또 하나 재미있었던 부분이 각기 다른 animation-duration 시간이었다. 포스트가 올라올 때마다 올라오는 시간이 모두 달랐는데 이것도 꼭 구현해보고 싶었다. 그러다 떠오른게 예전 유튜브에서 CSS로 구현한 커피의 수증기 표현이었다. 다행히 저장해놓은 것이 있어서 적용했는데 역시..! 나름 만족스러운 결과가 나왔다.
const randomNum = Math.floor(Math.random() * 7 + 5);
const article = document.createElement('article');
article.setAttribute('class', 'content');
article.setAttribute('style', `--i:${randomNum}`);
.content.animate {
animation: moveUp 0.65s;
animation-duration: calc(var(--i) * 0.07s);
opacity: 1;
}
신경쓴 부분들
- 모바일 반응(flex layout)
- 동적으로 생성되는 클래스
- 동적으로 클래스가 생성되기 때문에 첫화면이 위에 있든 아래에 있든(아래에서 새로고침 시) 애니메이션이 구현된다.
- 각기 다른 animation-duration 시간
- 부드러운 애니메이션
- 최대한 간결한 태그 깊이
- 부스트코스에서 웹 UI를 배울 때 지적을 많이 받은 부분이 '불필요한 태그를 생성하지 말라'는 것이었다. 깊이가 깊을수록 유지보수가 어렵고 성능상 좋지 않다는 이유였다.
- 그래서 최대한 간결한 뎁스를 유지하도록 노력했다.
- 전체 코드 보기
반응형
'JavaScript' 카테고리의 다른 글
new 연산자로 재사용성 높이기 (0) | 2021.11.01 |
---|---|
Node.js에서 스크래핑을 해보자 (0) | 2021.10.29 |
IntersectionObserver API로 무한 스크롤 만들기 (0) | 2021.10.08 |
IntersectionObserver API로 TOC 만들기 (0) | 2021.09.20 |
클로저(Closure) 이해하기 (0) | 2021.09.17 |